diff options
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.c | 836 |
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 */ +}; + |