summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c')
-rw-r--r--c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c836
1 files changed, 836 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c b/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c
new file mode 100644
index 0000000000..773f85b93a
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c
@@ -0,0 +1,836 @@
+/* This file contains the termios TTY driver for the Motorola MC68360 SCC ports.
+ *
+ * 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$
+ */
+
+#include <stdio.h>
+#include <termios.h>
+#include <bsp.h>
+#include <libcpu/io.h>
+#include <rtems/libio.h>
+#include <bsp/pci.h>
+#include <bsp/irq.h>
+#include <libchip/serial.h>
+#include "m68360.h"
+#include <libchip/sersupp.h>
+#include <stdlib.h>
+#include <rtems/bspIo.h>
+#include <string.h>
+
+#define MC68360_LENGHT_SIZE 100
+int mc68360_length_array[ MC68360_LENGHT_SIZE ];
+int mc68360_length_count=0;
+
+void mc68360_Show_length_array() {
+ int i;
+ for (i=0; i<MC68360_LENGHT_SIZE; i++)
+ printf(" %d", mc68360_length_array[i] );
+ printf("\n\n");
+}
+
+M68360_t M68360_chips = NULL;
+
+#define SYNC eieio
+
+void mc68360_scc_nullFunc() {}
+
+uint8_t scc_read8(
+ const char *name,
+ volatile uint8_t *address
+)
+{
+ uint8_t value;
+
+#ifdef DEBUG_360
+ printk( "RD8 %s 0x%08x ", name, address );
+#endif
+ value = *address;
+#ifdef DEBUG_360
+ printk( "0x%02x\n", value );
+#endif
+
+ return value;
+}
+
+void scc_write8(
+ const char *name,
+ volatile uint8_t *address,
+ uint8_t value
+)
+{
+#ifdef DEBUG_360
+ printk( "WR8 %s 0x%08x 0x%02x\n", name, address, value );
+#endif
+ *address = value;
+}
+
+
+uint16_t scc_read16(
+ const char *name,
+ volatile uint16_t *address
+)
+{
+ uint16_t value;
+
+#ifdef DEBUG_360
+ printk( "RD16 %s 0x%08x ", name, address );
+#endif
+ value = *address;
+#ifdef DEBUG_360
+ printk( "0x%04x\n", value );
+#endif
+
+ return value;
+}
+
+void scc_write16(
+ const char *name,
+ volatile uint16_t *address,
+ uint16_t value
+)
+{
+#ifdef DEBUG_360
+ printk( "WR16 %s 0x%08x 0x%04x\n", name, address, value );
+#endif
+ *address = value;
+}
+
+
+uint32_t scc_read32(
+ const char *name,
+ volatile uint32_t *address
+)
+{
+ uint32_t value;
+
+#ifdef DEBUG_360
+ printk( "RD32 %s 0x%08x ", name, address );
+#endif
+ value = *address;
+#ifdef DEBUG_360
+ printk( "0x%08x\n", value );
+#endif
+
+ return value;
+}
+
+void scc_write32(
+ const char *name,
+ volatile uint32_t *address,
+ uint32_t value
+)
+{
+#ifdef DEBUG_360
+ printk( "WR32 %s 0x%08x 0x%08x\n", name, address, value );
+#endif
+ *address = value;
+}
+
+void mc68360_sccShow_Regs(int minor){
+ M68360_serial_ports_t ptr;
+ ptr = Console_Port_Tbl[minor].pDeviceParams;
+
+ printk( "scce 0x%08x", &ptr->pSCCR->scce );
+ printk( " 0x%04x\n", ptr->pSCCR->scce );
+
+}
+
+#define TX_BUFFER_ADDRESS( _ptr ) \
+ ((char *)ptr->txBuf - (char *)ptr->chip->board_data->baseaddr)
+#define RX_BUFFER_ADDRESS( _ptr ) \
+ ((char *)ptr->rxBuf - (char *)ptr->chip->board_data->baseaddr)
+
+
+/**************************************************************************
+ * Function: mc68360_sccBRGC *
+ **************************************************************************
+ * Description: *
+ * *
+ * This function is called to compute the divisor register values for *
+ * a given baud rate. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * int baud - Baud rate (in bps). *
+ * *
+ * Output: *
+ * *
+ * int - baud rate generator configuration. *
+ * *
+ **************************************************************************/
+static int
+mc68360_sccBRGC(int baud, int m360_clock_rate)
+{
+ int data;
+
+ /*
+ * configure baud rate generator for 16x bit rate, where.....
+ * b = desired baud rate
+ * clk = system clock (33mhz)
+ * d = clock dividor value
+ *
+ * for b > 300 : d = clk/(b*16)
+ * for b<= 300 : d = (clk/ (b*16*16))-1)
+ */
+
+ SYNC();
+ if( baud > 300 ) data = 33333333 / (baud * 16 );
+ else data = (33333333 / (baud * 16 * 16) ) - 1;
+ data *= 2;
+ data &= 0x00001ffe ;
+
+ /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
+ data |= ((baud>300)? 0 : 1 ) ;
+ data |= 0x010000 ;
+
+ return data;
+}
+
+
+/**************************************************************************
+ * Function: sccInterruptHandler *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is the interrupt service routine for the console UART. It *
+ * handles both receive and transmit interrupts. The bulk of the *
+ * work is done by termios. *
+ * *
+ * Inputs: *
+ * *
+ * chip - structure of chip specific information *
+ * *
+ * Output: *
+ * *
+ * none *
+ * *
+ **************************************************************************/
+void mc68360_sccInterruptHandler( rtems_irq_hdl_param handle )
+{
+ volatile m360_t *m360;
+ int port;
+ uint16_t status;
+ uint16_t length;
+ int i;
+ char data;
+ int clear_isr;
+ M68360_t chip = (M68360_t)handle;
+
+ for (port=0; port<4; port++) {
+
+ clear_isr = FALSE;
+ m360 = chip->m360;
+
+ /*
+ * Handle a RX interrupt.
+ */
+ if ( scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x1)
+ {
+ clear_isr = TRUE;
+ scc_write16("scce", &chip->port[port].pSCCR->scce, 0x1 );
+ status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
+ while ((status & M360_BD_EMPTY) == 0)
+ {
+ length= scc_read16("sccRxBd->length",&chip->port[port].sccRxBd->length);
+ for (i=0;i<length;i++) {
+ data= chip->port[port].rxBuf[i];
+ rtems_termios_enqueue_raw_characters(
+ Console_Port_Data[ chip->port[port].minor ].termios_data,
+ &data,
+ 1);
+ }
+ scc_write16( "sccRxBd->status", &chip->port[port].sccRxBd->status,
+ M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
+ status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
+ }
+ }
+
+ /*
+ * Handle a TX interrupt.
+ */
+ if (scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x2)
+ {
+ clear_isr = TRUE;
+ scc_write16("scce", &chip->port[port].pSCCR->scce, 0x2);
+ status = scc_read16("sccTxBd->status", &chip->port[port].sccTxBd->status);
+ if ((status & M360_BD_EMPTY) == 0)
+ {
+ scc_write16("sccTxBd->status",&chip->port[port].sccTxBd->status,0);
+ rtems_termios_dequeue_characters(
+ Console_Port_Data[chip->port[port].minor].termios_data,
+ chip->port[port].sccTxBd->length);
+ }
+ }
+
+ /*
+ * Clear SCC interrupt-in-service bit.
+ */
+ if ( clear_isr )
+ scc_write32( "cisr", &m360->cisr, (0x80000000 >> chip->port[port].channel) );
+ }
+}
+
+/*
+ * mc68360_scc_open
+ *
+ * This function opens a port for communication.
+ *
+ * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
+ */
+
+int mc68360_scc_open(
+ int major,
+ int minor,
+ void * arg
+)
+{
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * mc68360_scc_initialize_interrupts
+ *
+ * This routine initializes the console's receive and transmit
+ * ring buffers and loads the appropriate vectors to handle the interrupts.
+ */
+
+void mc68360_scc_initialize_interrupts(int minor)
+{
+ M68360_serial_ports_t ptr;
+ volatile m360_t *m360;
+ uint32_t data;
+ uint32_t buffers_start;
+ uint32_t tmp_u32;
+
+#ifdef DEBUG_360
+ printk("mc68360_scc_initialize_interrupts: minor %d\n", minor );
+ printk("Console_Port_Tbl[minor].pDeviceParams 0x%08x\n",
+ Console_Port_Tbl[minor].pDeviceParams );
+#endif
+
+ ptr = Console_Port_Tbl[minor].pDeviceParams;
+ m360 = ptr->chip->m360;
+#ifdef DEBUG_360
+ printk("m360 0x%08x baseaddr 0x%08x\n",
+ m360, ptr->chip->board_data->baseaddr);
+#endif
+
+ buffers_start = ptr->chip->board_data->baseaddr + 0x00200000 +
+ ( (M68360_RX_BUF_SIZE + M68360_TX_BUF_SIZE) * (ptr->channel-1));
+ ptr->rxBuf = (uint8_t *) buffers_start;
+ ptr->txBuf = (uint8_t *)(buffers_start + M68360_RX_BUF_SIZE);
+#ifdef DEBUG_360
+ printk("rxBuf 0x%08x txBuf 0x%08x\n", ptr->rxBuf, ptr->txBuf );
+#endif
+ /*
+ * Set Channel Drive Enable bits in EPLD
+ */
+ data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
+ SYNC();
+ data |= (PMCQ1_DRIVER_ENABLE_3 | PMCQ1_DRIVER_ENABLE_2 |
+ PMCQ1_DRIVER_ENABLE_1 | PMCQ1_DRIVER_ENABLE_0);
+ PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE, data);
+ data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
+ SYNC();
+
+ /*
+ * Disable the receiver and the transmitter.
+ */
+
+ SYNC();
+ tmp_u32 = scc_read32( "gsmr_l", &ptr->pSCCR->gsmr_l );
+ tmp_u32 &= (~(M360_GSMR_ENR | M360_GSMR_ENT ) ) ;
+ scc_write32( "gsmr_l", &ptr->pSCCR->gsmr_l, tmp_u32 );
+
+ /*
+ * Disable Interrupt Error and Interrupt Breakpoint
+ * Set SAID to 4 XXX - Shouldn't it be 7 for slave mode
+ * Set SAISM to 7
+ */
+ SYNC();
+ scc_write16( "sdcr", &m360->sdcr, 0x0740 );
+
+ /*
+ * Clear status -- reserved interrupt, SDMA channel error, SDMA breakpoint
+ */
+ scc_write8( "sdsr", &m360->sdsr, 0x07 );
+ SYNC();
+
+ /*
+ * Initialize timer information in RISC Controller Configuration Register
+ */
+ scc_write16( "rccr", &m360->rccr, 0x8100 );
+ SYNC();
+
+ /*
+ * XXX
+ */
+ scc_write16( "papar", &m360->papar, 0xffff );
+ scc_write16( "padir", &m360->padir, 0x5500 ); /* From Memo */
+ scc_write16( "paodr", &m360->paodr, 0x0000 );
+ SYNC();
+
+ /*
+ * XXX
+ */
+ scc_write32( "pbpar", &m360->pbpar, 0x00000000 );
+ scc_write32( "pbdir", &m360->pbdir, 0x0003ffff );
+ scc_write32( "pbdat", &m360->pbdat, 0x0000003f );
+ SYNC();
+
+ /*
+ * XXX
+ */
+ scc_write16( "pcpar", &m360->pcpar, 0x0000 );
+ scc_write16( "pcdir", &m360->pcdir, 0x0000 );
+ scc_write16( "pcso", &m360->pcso, 0x0000 );
+ SYNC();
+
+ /*
+ * configure baud rate generator for 16x bit rate, where.....
+ * b = desired baud rate
+ * clk = system clock (33mhz)
+ * d = clock dividor value
+ *
+ * for b > 300 : d = clk/(b*16)
+ * for b<= 300 : d = (clk/ (b*16*16))-1)
+ */
+ SYNC();
+ if( ptr->baud > 300 ) data = 33333333 / (ptr->baud * 16 );
+ else data = (33333333 / (ptr->baud * 16 * 16) ) - 1;
+ data *= 2 ;
+ data &= 0x00001ffe ;
+
+ /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
+ data |= ((ptr->baud>300)? 0 : 1 ) ;
+ data |= 0x010000 ;
+
+ scc_write32( "pBRGC", ptr->pBRGC, data );
+
+ data = (((ptr->channel-1)*8) | (ptr->channel-1)) ;
+ data = data << ((ptr->channel-1)*8) ;
+ data |= scc_read32( "sicr", &m360->sicr );
+ scc_write32( "sicr", &m360->sicr, data );
+
+ /*
+ * initialise SCC parameter ram
+ */
+ SYNC();
+ scc_write16( "pSCCB->rbase", &ptr->pSCCB->rbase,
+ (char *)(ptr->sccRxBd) - (char *)m360 );
+ scc_write16( "pSCCB->tbase", &ptr->pSCCB->tbase,
+ (char *)(ptr->sccTxBd) - (char *)m360 );
+
+ scc_write8( "pSCCB->rfcr", &ptr->pSCCB->rfcr, 0x15 ); /* 0x15 0x18 */
+ scc_write8( "pSCCB->tfcr", &ptr->pSCCB->tfcr, 0x15 ); /* 0x15 0x18 */
+
+ scc_write16( "pSCCB->mrblr", &ptr->pSCCB->mrblr, M68360_RX_BUF_SIZE );
+
+ /*
+ * initialise tx and rx scc parameters
+ */
+ SYNC();
+ data = M360_CR_INIT_TX_RX_PARAMS | 0x01;
+ data |= (M360_CR_CH_NUM * (ptr->channel-1) );
+ scc_write16( "CR", &m360->cr, data );
+
+ /*
+ * initialise uart specific parameter RAM
+ */
+ SYNC();
+ scc_write16( "pSCCB->un.uart.max_idl", &ptr->pSCCB->un.uart.max_idl, 15000 );
+ scc_write16( "pSCCB->un.uart.brkcr", &ptr->pSCCB->un.uart.brkcr, 0x0001 );
+ scc_write16( "pSCCB->un.uart.parec", &ptr->pSCCB->un.uart.parec, 0x0000 );
+
+ scc_write16( "pSCCB->un,uart.frmec", &ptr->pSCCB->un.uart.frmec, 0x0000 );
+
+ scc_write16( "pSCCB->un.uart.nosec", &ptr->pSCCB->un.uart.nosec, 0x0000 );
+ scc_write16( "pSCCB->un.uart.brkec", &ptr->pSCCB->un.uart.brkec, 0x0000 );
+ scc_write16( "pSCCB->un.uart.uaddr0", &ptr->pSCCB->un.uart.uaddr[0], 0x0000 );
+ scc_write16( "pSCCB->un.uart.uaddr1", &ptr->pSCCB->un.uart.uaddr[1], 0x0000 );
+ scc_write16( "pSCCB->un.uart.toseq", &ptr->pSCCB->un.uart.toseq, 0x0000 );
+ scc_write16( "pSCCB->un.uart.char0",
+ &ptr->pSCCB->un.uart.character[0], 0x0039 );
+ scc_write16( "pSCCB->un.uart.char1",
+ &ptr->pSCCB->un.uart.character[1], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char2",
+ &ptr->pSCCB->un.uart.character[2], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char3",
+ &ptr->pSCCB->un.uart.character[3], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char4",
+ &ptr->pSCCB->un.uart.character[4], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char5",
+ &ptr->pSCCB->un.uart.character[5], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char6",
+ &ptr->pSCCB->un.uart.character[6], 0x8000 );
+ scc_write16( "pSCCB->un.uart.char7",
+ &ptr->pSCCB->un.uart.character[7], 0x8000 );
+
+ scc_write16( "pSCCB->un.uart.rccm", &ptr->pSCCB->un.uart.rccm, 0xc0ff );
+
+ /*
+ * setup buffer descriptor stuff
+ */
+ SYNC();
+ scc_write16( "sccRxBd->status", &ptr->sccRxBd->status, 0x0000 );
+ SYNC();
+ scc_write16( "sccRxBd->length", &ptr->sccRxBd->length, 0x0000 );
+ scc_write16( "sccRxBd->status", &ptr->sccRxBd->status,
+ M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
+ /* XXX Radstone Example writes RX buffer ptr as two u16's */
+ scc_write32( "sccRxBd->buffer", &ptr->sccRxBd->buffer,
+ RX_BUFFER_ADDRESS( ptr ) );
+
+ SYNC();
+ scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0x0000 );
+ SYNC();
+ scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, 0x0000 );
+ /* XXX Radstone Example writes TX buffer ptr as two u16's */
+ scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
+ TX_BUFFER_ADDRESS( ptr ) );
+
+ /*
+ * clear previous events and set interrupt priorities
+ */
+ scc_write16( "pSCCR->scce", &ptr->pSCCR->scce, 0x1bef ); /* From memo */
+ SYNC();
+ SYNC();
+ scc_write32( "cicr", &m360->cicr, 0x001b9f40 );
+ SYNC();
+
+ /* scc_write32( "cicr", &m360->cicr, scc_read32( "cicr", &m360->cicr ) ); */
+
+ scc_write16( "pSCCR->sccm", &ptr->pSCCR->sccm, M360_SCCE_TX | M360_SCCE_RX );
+
+ data = scc_read32("cimr", &m360->cimr);
+ data |= (0x80000000 >> ptr->channel);
+ scc_write32( "cimr", &m360->cimr, data );
+ SYNC();
+ scc_write32( "cipr", &m360->cipr, scc_read32( "cipr", &m360->cipr ) );
+
+ scc_write32( "pSCCR->gsmr_h", &ptr->pSCCR->gsmr_h, M360_GSMR_RFW );
+ scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
+ (M360_GSMR_TDCR_16X | M360_GSMR_RDCR_16X | M360_GSMR_MODE_UART) );
+
+ scc_write16( "pSCCR->dsr", &ptr->pSCCR->dsr, 0x7e7e );
+ SYNC();
+
+ scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr,
+ (M360_PSMR_CL8 | M360_PSMR_UM_NORMAL | M360_PSMR_TPM_ODD) );
+ SYNC();
+
+ /*
+ * Enable the receiver and the transmitter.
+ */
+
+ SYNC();
+ data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l);
+ scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
+ (data | M360_GSMR_ENR | M360_GSMR_ENT) );
+
+ data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK );
+ data &= (~PMCQ1_INT_MASK_QUICC);
+ PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data );
+
+ data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS );
+ data &= (~PMCQ1_INT_STATUS_QUICC);
+ PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data );
+}
+
+/*
+ * mc68360_scc_write_support_int
+ *
+ * Console Termios output entry point when using interrupt driven output.
+ */
+
+int mc68360_scc_write_support_int(
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ rtems_interrupt_level Irql;
+ M68360_serial_ports_t ptr;
+
+ mc68360_length_array[ mc68360_length_count ] = len;
+ mc68360_length_count++;
+ if ( mc68360_length_count >= MC68360_LENGHT_SIZE )
+ mc68360_length_count=0;
+
+ ptr = Console_Port_Tbl[minor].pDeviceParams;
+
+ /*
+ * We are using interrupt driven output and termios only sends us
+ * one character at a time.
+ */
+
+ if ( !len )
+ return 0;
+
+ /*
+ *
+ */
+#ifdef DEBUG_360
+ printk("mc68360_scc_write_support_int: char 0x%x length %d\n",
+ (unsigned int)*buf, len );
+#endif
+ /*
+ * We must copy the data from the global memory space to MC68360 space
+ */
+
+ rtems_interrupt_disable(Irql);
+
+ scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0 );
+ memcpy((void *) ptr->txBuf, buf, len);
+ scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
+ TX_BUFFER_ADDRESS(ptr->txBuf) );
+ scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, len );
+ scc_write16( "sccTxBd->status", &ptr->sccTxBd->status,
+ (M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT) );
+
+ rtems_interrupt_enable(Irql);
+
+ return len;
+}
+
+/*
+ * mc68360_scc_write_polled
+ *
+ * This routine polls out the requested character.
+ */
+
+void mc68360_scc_write_polled(
+ int minor,
+ char cChar
+)
+{
+#ifdef DEBUG_360
+ printk("mc68360_scc_write_polled: %c\n", cChar);
+#endif
+}
+
+/*
+ * mc68681_set_attributes
+ *
+ * This function sets the DUART channel to reflect the requested termios
+ * port settings.
+ */
+
+int mc68360_scc_set_attributes(
+ int minor,
+ const struct termios *t
+)
+{
+ int baud;
+ volatile m360_t *m360;
+ M68360_serial_ports_t ptr;
+
+ ptr = Console_Port_Tbl[minor].pDeviceParams;
+ m360 = ptr->chip->m360;
+
+ switch (t->c_cflag & CBAUD)
+ {
+ 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;
+ default: baud = -1; break;
+ }
+
+ if (baud > 0)
+ {
+ scc_write32(
+ "pBRGC",
+ ptr->pBRGC,
+ mc68360_sccBRGC(baud, ptr->chip->m360_clock_rate)
+ );
+ }
+
+ return 0;
+}
+
+/*
+ * mc68360_scc_close
+ *
+ * This function shuts down the requested port.
+ */
+
+int mc68360_scc_close(
+ int major,
+ int minor,
+ void *arg
+)
+{
+ return(RTEMS_SUCCESSFUL);
+}
+
+/*
+ * mc68360_scc_inbyte_nonblocking_polled
+ *
+ * Console Termios polling input entry point.
+ */
+
+int mc68360_scc_inbyte_nonblocking_polled(
+ int minor
+)
+{
+ return -1;
+}
+
+/*
+ * mc68360_scc_write_support_polled
+ *
+ * Console Termios output entry point when using polled output.
+ *
+ */
+
+int mc68360_scc_write_support_polled(
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ printk("mc68360_scc_write_support_polled: minor %d char %c len %d\n",
+ minor, buf, len );
+ return 0;
+}
+
+/*
+ * mc68360_scc_init
+ *
+ * This function initializes the DUART to a quiecsent state.
+ */
+
+void mc68360_scc_init(int minor)
+{
+#ifdef DEBUG_360
+ printk("mc68360_scc_init\n");
+#endif
+}
+
+int mc68360_scc_create_chip( PPMCQ1BoardData BoardData, uint8_t int_vector )
+{
+ M68360_t chip;
+ int i;
+
+#ifdef DEBUG_360
+ printk("mc68360_scc_create_chip\n");
+#endif
+
+ /*
+ * Create console structure for this card
+ * XXX - Note Does this need to be moved up to if a QUICC is fitted
+ * section?
+ */
+ if ((chip = malloc(sizeof(struct _m68360_per_chip))) == NULL)
+ {
+ printk("Error Unable to allocate memory for _m68360_per_chip\n");
+ return RTEMS_IO_ERROR;
+ }
+
+ chip->next = M68360_chips;
+ chip->m360 = (void *)BoardData->baseaddr;
+ chip->m360_interrupt = int_vector;
+ chip->m360_clock_rate = 25000000;
+ chip->board_data = BoardData;
+ M68360_chips = chip;
+
+ for (i=1; i<=4; i++) {
+ chip->port[i-1].channel = i;
+ chip->port[i-1].chip = chip;
+ chip->port[i-1].baud = 9600;
+
+ switch( i ) {
+ case 1:
+ chip->port[i-1].pBRGC = &chip->m360->brgc1;
+ chip->port[i-1].pSCCB = (m360SCCparms_t *) &chip->m360->scc1p;
+ chip->port[i-1].pSCCR = &chip->m360->scc1;
+ M360SetupMemory( chip ); /* Do this first time through */
+ break;
+ case 2:
+ chip->port[i-1].pBRGC = &chip->m360->brgc2;
+ chip->port[i-1].pSCCB = &chip->m360->scc2p;
+ chip->port[i-1].pSCCR = &chip->m360->scc2;
+ break;
+ case 3:
+ chip->port[i-1].pBRGC = &chip->m360->brgc3;
+ chip->port[i-1].pSCCB = &chip->m360->scc3p;
+ chip->port[i-1].pSCCR = &chip->m360->scc3;
+ break;
+ case 4:
+ chip->port[i-1].pBRGC = &chip->m360->brgc4;
+ chip->port[i-1].pSCCB = &chip->m360->scc4p;
+ chip->port[i-1].pSCCR = &chip->m360->scc4;
+ break;
+ default:
+ printk("Invalid mc68360 channel %d\n", i);
+ return RTEMS_IO_ERROR;
+ }
+
+ /*
+ * Allocate buffer descriptors.
+ */
+
+ chip->port[i-1].sccRxBd = M360AllocateBufferDescriptors(chip, 1);
+ chip->port[i-1].sccTxBd = M360AllocateBufferDescriptors(chip, 1);
+ }
+
+ rsPMCQ1QuiccIntConnect(
+ chip->board_data->busNo,
+ chip->board_data->slotNo,
+ chip->board_data->funcNo,
+ &mc68360_sccInterruptHandler,
+ chip
+ );
+
+ return RTEMS_SUCCESSFUL;
+}
+
+console_fns mc68360_scc_fns = {
+ libchip_serial_default_probe, /* deviceProbe */
+ mc68360_scc_open, /* deviceFirstOpen */
+ NULL, /* deviceLastClose */
+ NULL, /* deviceRead */
+ mc68360_scc_write_support_int, /* deviceWrite */
+ mc68360_scc_initialize_interrupts, /* deviceInitialize */
+ mc68360_scc_write_polled, /* deviceWritePolled */
+ mc68360_scc_set_attributes, /* deviceSetAttributes */
+ TRUE /* deviceOutputUsesInterrupts */
+};
+
+console_fns mc68360_scc_polled = {
+ libchip_serial_default_probe, /* deviceProbe */
+ mc68360_scc_open, /* deviceFirstOpen */
+ mc68360_scc_close, /* deviceLastClose */
+ mc68360_scc_inbyte_nonblocking_polled, /* deviceRead */
+ mc68360_scc_write_support_polled, /* deviceWrite */
+ mc68360_scc_init, /* deviceInitialize */
+ mc68360_scc_write_polled, /* deviceWritePolled */
+ mc68360_scc_set_attributes, /* deviceSetAttributes */
+ FALSE /* deviceOutputUsesInterrupts */
+};
+