summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/leon3/console
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/leon3/console')
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/Makefile.am2
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/console.c63
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/debugprintf.c180
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/debugputs.c26
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/spacewire.c677
5 files changed, 911 insertions, 37 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/console/Makefile.am b/c/src/lib/libbsp/sparc/leon3/console/Makefile.am
index 0d5e07e99e..9b887189e7 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/console/Makefile.am
@@ -5,7 +5,7 @@
PGM = $(ARCH)/console.rel
-C_FILES = console.c consolereserveresources.c debugputs.c
+C_FILES = console.c spacewire.c consolereserveresources.c debugputs.c debugprintf.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT))
OBJS = $(C_O_FILES)
diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index 41dd26c449..966bad0948 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -85,8 +85,29 @@ int console_write_support (int minor, const char *buf, int len)
* Console Device Driver Entry Points
*
*/
+int uarts = 0;
+static int isinit = 0;
+volatile LEON3_UART_Regs_Map *LEON3_Console_Uart[LEON3_APBUARTS];
+
+int scan_uarts() {
+ unsigned int iobar, conf;
+ int i;
+ if (isinit == 0) {
+ i = 0; uarts = 0;
+ while (i < amba_conf.apbslv.devnr) {
+ conf = amba_get_confword(amba_conf.apbslv, i, 0);
+ if ((amba_vendor(conf) == VENDOR_GAISLER) && (amba_device(conf) == GAISLER_APBUART)){
+ iobar = amba_apb_get_membar(amba_conf.apbslv, i);
+ LEON3_Console_Uart[uarts] = (volatile LEON3_UART_Regs_Map *) amba_iobar_start(amba_conf.apbmst, iobar);
+ uarts++;
+ }
+ i++;
+ }
+ isinit = 1;
+ }
+ return uarts;
+}
-volatile LEON3_UART_Regs_Map *LEON3_Console_Uart[LEON3_APBUARTS];
rtems_device_driver console_initialize(
rtems_device_major_number major,
@@ -95,52 +116,48 @@ rtems_device_driver console_initialize(
)
{
rtems_status_code status;
- unsigned int iobar, conf;
- int i, uarts;
+ int i;
char *console_name = "/dev/console_a";
-
+ extern rtems_configuration_table Configuration;
+ int uart0;
rtems_termios_initialize();
/* Find UARTs */
-
- i = 0; uarts = 0;
- while (i < amba_conf.apbslv.devnr)
- {
- conf = amba_get_confword(amba_conf.apbslv, i, 0);
- if ((amba_vendor(conf) == VENDOR_GAISLER) && (amba_device(conf) == GAISLER_APBUART))
- {
- iobar = amba_apb_get_membar(amba_conf.apbslv, i);
- LEON3_Console_Uart[uarts] = (volatile LEON3_UART_Regs_Map *) amba_iobar_start(amba_conf.apbmst, iobar);
- uarts++;
- }
- i++;
- }
+ scan_uarts();
+ if (Configuration.User_multiprocessing_table != NULL)
+ uart0 = LEON3_Cpu_Index;
+ else
+ uart0 = 0;
+
/* Register Device Names */
- if (uarts)
+ if (uarts && (uart0 < uarts))
{
status = rtems_io_register_name( "/dev/console", major, 0 );
if (status != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred(status);
- for (i = 1; i < uarts; i++)
+ for (i = uart0+1; i < uarts; i++)
{
console_name[13]++;
status = rtems_io_register_name( console_name, major, i);
}
}
-
/*
* Initialize Hardware
*/
- for (i = 0; i < uarts; i++)
+ if ((Configuration.User_multiprocessing_table == NULL) ||
+ ((Configuration.User_multiprocessing_table)->node == 1))
{
- LEON3_Console_Uart[i]->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
- LEON3_Console_Uart[i]->status = 0;
+ for (i = uart0; i < uarts; i++)
+ {
+ LEON3_Console_Uart[i]->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
+ LEON3_Console_Uart[i]->status = 0;
+ }
}
return RTEMS_SUCCESSFUL;
diff --git a/c/src/lib/libbsp/sparc/leon3/console/debugprintf.c b/c/src/lib/libbsp/sparc/leon3/console/debugprintf.c
new file mode 100644
index 0000000000..39d80d0cf6
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/console/debugprintf.c
@@ -0,0 +1,180 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Modified for LEON3 BSP.
+ * COPYRIGHT (c) 2004.
+ * Gaisler Research.
+ *
+ * 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 <bsp.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdarg.h>
+
+static size_t lo_strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+static int lo_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i,j,n;
+ char *str, *end, c;
+ const char *s;
+ int flags;
+ int field_width;
+ int precision;
+ int qualifier;
+
+ str = buf;
+ end = buf + size - 1;
+
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ size = end - buf + 1;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ /* get field width */
+ field_width = -1;
+ /* get the precision */
+ precision = -1;
+ /* get the conversion qualifier */
+ qualifier = 'l';
+
+ ++fmt;
+ /* default base */
+ switch (*fmt) {
+ case 'c':
+ c = (unsigned char) va_arg(args, int);
+ if (str <= end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = lo_strnlen(s, precision);
+
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+
+ case '%':
+ if (str <= end)
+ *str = '%';
+ ++str;
+ continue;
+
+ case 'x':
+ break;
+
+ default:
+ if (str <= end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else {
+ --fmt;
+ }
+ continue;
+ }
+ num = va_arg(args, unsigned long);
+ for (j=0,i=0;i<8 && str <= end;i++) {
+ if ( (n = ((unsigned long)(num & (0xf0000000ul>>(i*4)))) >> ((7-i)*4)) || j != 0) {
+ j = 1;
+ if (n >= 10)
+ n += 'a'-10;
+ else
+ n += '0';
+ *str = n;
+ ++str;
+ }
+ }
+ if (j == 0 && str <= end) {
+ *str = '0';
+ ++str;
+ }
+ }
+ if (str <= end)
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str-buf;
+}
+
+int DEBUG_sprintf(char *buf, size_t size, const char *fmt, ...) {
+ va_list args;
+ int printed_len;
+
+ va_start(args, fmt);
+ printed_len = lo_vsnprintf(buf, size, fmt, args);
+ va_end(args);
+ return printed_len;
+}
+
+int scan_uarts();
+void DEBUG_puts( char *string );
+int DEBUG_printf(const char *fmt, ...)
+{
+ va_list args;
+ int printed_len;
+ char printk_buf[1024+1];
+
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ printed_len = lo_vsnprintf(printk_buf, sizeof(printk_buf)-1, fmt, args);
+ printk_buf[printed_len] = 0;
+ va_end(args);
+
+ scan_uarts();
+ /*DEBUG_puts(printk_buf);*/
+ return printed_len;
+}
diff --git a/c/src/lib/libbsp/sparc/leon3/console/debugputs.c b/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
index 066a584386..7e3ea655d9 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
@@ -35,8 +35,8 @@ void console_outbyte_polled(
{
if ((port >= 0) && (port <= CONFIGURE_NUMBER_OF_TERMIOS_PORTS))
{
- while ( (LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_THE) == 0 );
- LEON3_Console_Uart[port]->data = (unsigned int) ch;
+ while ( (LEON3_Console_Uart[LEON3_Cpu_Index+port]->status & LEON_REG_UART_STATUS_THE) == 0 );
+ LEON3_Console_Uart[LEON3_Cpu_Index+port]->data = (unsigned int) ch;
}
}
@@ -52,13 +52,13 @@ int console_inbyte_nonblocking( int port )
if ((port >=0) && (port < CONFIGURE_NUMBER_OF_TERMIOS_PORTS))
{
- if (LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_ERR) {
- LEON3_Console_Uart[port]->status = ~LEON_REG_UART_STATUS_ERR;
+ if (LEON3_Console_Uart[LEON3_Cpu_Index+port]->status & LEON_REG_UART_STATUS_ERR) {
+ LEON3_Console_Uart[LEON3_Cpu_Index+port]->status = ~LEON_REG_UART_STATUS_ERR;
}
- if ((LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_DR) == 0)
+ if ((LEON3_Console_Uart[LEON3_Cpu_Index+port]->status & LEON_REG_UART_STATUS_DR) == 0)
return -1;
- return (int) LEON3_Console_Uart[port]->data;
+ return (int) LEON3_Console_Uart[LEON3_Cpu_Index+port]->data;
}
else
@@ -90,15 +90,15 @@ void DEBUG_puts(
{
char *s;
/* unsigned32 old_level; */
-
+
/* LEON_Disable_interrupt( LEON_INTERRUPT_UART_1_RX_TX, old_level ); */
sparc_disable_interrupts();
LEON3_Console_Uart[0]->ctrl = LEON_REG_UART_CTRL_TE;
- for ( s = string ; *s ; s++ )
- console_outbyte_polled( 0, *s );
-
- console_outbyte_polled( 0, '\r' );
- console_outbyte_polled( 0, '\n' );
+ for ( s = string ; *s ; s++ )
+ console_outbyte_polled( 0, *s );
+
+ console_outbyte_polled( 0, '\r' );
+ console_outbyte_polled( 0, '\n' );
sparc_enable_interrupts();
- /* LEON_Restore_interrupt( LEON_INTERRUPT_UART_1_RX_TX, old_level ); */
+ /* LEON_Restore_interrupt( LEON_INTERRUPT_UART_1_RX_TX, old_level ); */
}
diff --git a/c/src/lib/libbsp/sparc/leon3/console/spacewire.c b/c/src/lib/libbsp/sparc/leon3/console/spacewire.c
new file mode 100644
index 0000000000..a0460a4027
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/console/spacewire.c
@@ -0,0 +1,677 @@
+/*
+ * This file contains the TTY driver for the spacewire port on the LEON.
+ *
+ * This driver uses the termios pseudo driver.
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Modified for LEON3 BSP.
+ * COPYRIGHT (c) 2005.
+ * Gaisler Research.
+ *
+ * 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.
+ *
+ * spacewire.c,v 1.1.2.1 2005/11/02 19:25:59 jiri Exp
+ */
+
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sched.h>
+#include <ctype.h>
+#include <rtems/bspIo.h>
+
+#define DBGSPW_IOCALLS 1
+#define DBGSPW_TX 2
+#define DBGSPW_RX 4
+#define DBGSPW_IOCTRL 8
+#define DBGSPW_DUMP 16
+#define DEBUG_SPACEWIRE_FLAGS -1
+
+/*#define DEBUG_SPACEWIRE_ONOFF*/
+
+#ifdef DEBUG_SPACEWIRE_ONOFF
+int DEBUG_printf(const char *fmt, ...);
+#define SPACEWIRE_DBG(fmt, args...) \
+ do { \
+ { printf(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args); } \
+ } while(0)
+#define SPACEWIRE_DBG2(fmt) \
+ do { \
+ { printf(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__); } \
+ } while(0)
+#define SPACEWIRE_DBGC(c,fmt, args...) \
+ do { \
+ if (DEBUG_SPACEWIRE_FLAGS&c) { \
+ printf(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args); \
+ } \
+ } while(0)
+#else
+#define SPACEWIRE_DBG(fmt, args...)
+#define SPACEWIRE_DBG2(fmt, args...)
+#define SPACEWIRE_DBGC(fmt, args...)
+#endif
+
+int spacewire_hw_init(int minor);
+void spacewire_hw_send(int minor,unsigned char *b,int c);
+int spacewire_hw_receive(int minor,unsigned char *b,int c);
+int spacewire_hw_startup (int minor);
+int spacewire_hw_stop (int minor);
+void spacewire_hw_waitlink (int minor);
+void spacewire_rxnext(int minor);
+
+int _SPW_READ(void *addr) {
+ int tmp;
+ asm(" lda [%1]1, %0 "
+ : "=r"(tmp)
+ : "r"(addr)
+ );
+ return tmp;
+}
+
+rtems_device_driver spacewire_console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+rtems_device_driver spacewire_console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+rtems_device_driver spacewire_console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+rtems_device_driver spacewire_console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+rtems_device_driver spacewire_console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+rtems_device_driver spacewire_console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+#define SPWCEWIRE_CONSOLE_DRIVER_TABLE_ENTRY \
+ { spacewire_console_initialize, spacewire_console_open, \
+ spacewire_console_close, spacewire_console_read, \
+ spacewire_console_write, spacewire_console_control }
+
+static rtems_driver_address_table
+ spacewire_driver = SPWCEWIRE_CONSOLE_DRIVER_TABLE_ENTRY;
+
+void spacewire_register()
+{
+ rtems_status_code r;
+ rtems_device_major_number m;
+
+ SPACEWIRE_DBG2("register driver\n");
+ if ((r = rtems_io_register_driver(
+ 0,
+ &spacewire_driver,
+ &m)) == RTEMS_SUCCESSFUL) {
+ SPACEWIRE_DBG2("success\n");
+ } else {
+ switch(r) {
+ case RTEMS_TOO_MANY:
+ SPACEWIRE_DBG2("failed RTEMS_TOO_MANY\n"); break;
+ case RTEMS_INVALID_NUMBER:
+ SPACEWIRE_DBG2("failed RTEMS_INVALID_NUMBER\n"); break;
+ case RTEMS_RESOURCE_IN_USE:
+ SPACEWIRE_DBG2("failed RTEMS_RESOURCE_IN_USE\n"); break;
+ default:
+ SPACEWIRE_DBG("failed %i\n",r); break;
+ }
+ }
+}
+
+#ifdef SPW_BUFMALLOC
+void spacewire_buffer_alloc(int minor) {
+ if (SPW_PARAM(minor).ptr_rxbuf0) {
+ free(SPW_PARAM(minor).ptr_rxbuf0);
+ }
+ if (SPW_PARAM(minor).ptr_txbuf0) {
+ free(SPW_PARAM(minor).ptr_txbuf0);
+ }
+ SPW_PARAM(minor).ptr_rxbuf0 =
+ (char *) malloc(SPW_PARAM(minor).rxbufsize * SPW_PARAM(minor).rxbufcnt);
+ SPW_PARAM(minor).ptr_txbuf0 =
+ (char *) malloc(SPW_PARAM(minor).txbufsize * SPW_PARAM(minor).txbufcnt);
+}
+#endif
+
+/*
+ * Console Device Driver Entry Points
+ *
+ */
+
+SPACEWIRE_PARAM LEON3_Spacewire[SPACEWIRE_MAX_CORENR];
+
+rtems_device_driver spacewire_console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+ unsigned int iobar, conf;
+ int i, uarts;
+ char *console_name = "/dev/spacewire_a";
+ SPACEWIRE_DBG2("spacewire driver inizialisation\n");
+
+ rtems_termios_initialize();
+
+ /* Find spacewire cores */
+ i = 0; uarts = 0;
+ while (i < amba_conf.apbslv.devnr && uarts < SPACEWIRE_MAX_CORENR)
+ {
+ conf = amba_get_confword(amba_conf.apbslv, i, 0);
+ if ((amba_vendor(conf) == VENDOR_GAISLER) &&
+ (amba_device(conf) == GAISLER_SPACEWIRE))
+ {
+ iobar = amba_apb_get_membar(amba_conf.apbslv, i);
+ LEON3_Spacewire[uarts].regs =
+ (LEON3_SPACEWIRE_Regs_Map *) amba_iobar_start(amba_conf.apbmst, iobar);
+ LEON3_Spacewire[uarts].irq = amba_irq(conf);
+
+ SPACEWIRE_DBG("spacewire code at [0x%x]\n",
+ (unsigned int)LEON3_Spacewire[uarts].regs);
+
+ /* initialize the code with some resonable values,
+ actual initialization is done later using ioctl(fd)
+ on the opened device */
+ LEON3_Spacewire[uarts].nodeaddr = 0x14;
+ LEON3_Spacewire[uarts].destkey = 0xBF;
+ LEON3_Spacewire[uarts].maxfreq = 1;
+ LEON3_Spacewire[uarts].clkdiv = 0;
+ LEON3_Spacewire[uarts].rxmaxlen = SPACEWIRE_RXPCK_SIZE;
+ LEON3_Spacewire[uarts].txbufsize = SPACEWIRE_TXPCK_SIZE;
+ LEON3_Spacewire[uarts].rxbufsize = SPACEWIRE_RXPCK_SIZE;
+ LEON3_Spacewire[uarts].txbufcnt = SPACEWIRE_TXBUFS_NR;
+ LEON3_Spacewire[uarts].rxbufcnt = SPACEWIRE_RXBUFS_NR;
+
+#ifndef SPW_BUFMALLOC
+ LEON3_Spacewire[uarts].ptr_rxbuf0 = &LEON3_Spacewire[uarts]._rxbuf0;
+ LEON3_Spacewire[uarts].ptr_txbuf0 = &LEON3_Spacewire[uarts]._txbuf0;
+#else
+ LEON3_Spacewire[uarts].ptr_rxbuf0 = 0;
+ LEON3_Spacewire[uarts].ptr_txbuf0 = 0;
+ spacewire_buffer_alloc(uarts);
+#endif
+ uarts++;
+ }
+ i++;
+ }
+
+ /* Register Device Names, /dev/spacewire, /dev/spacewire_b ... */
+ if (uarts) {
+ SPACEWIRE_DBG2("registering minor 0 as /dev/spacewire\n");
+ status = rtems_io_register_name( "/dev/spacewire", major, 0 );
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ for (i = 1; i < uarts; i++) {
+ console_name[15]++;
+ SPACEWIRE_DBG("registering minor %i as %s\n",i,console_name);
+ status = rtems_io_register_name( console_name, major, i);
+ }
+ }
+
+ /* Initialize Hardware */
+ for (i = 0; i < uarts; i++) {
+ spacewire_hw_init(i);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+int spacewire_setattibutes(int minor, int nodeaddr, int proto, int dest) {
+ if ( minor >= SPACEWIRE_MAX_CORENR ) {
+ printf("minor %i too big\n",minor);
+ return RTEMS_INVALID_NUMBER;
+ }
+ SPW_PARAM(minor).nodeaddr = nodeaddr;
+ SPW_PARAM(minor).proto = proto;
+ SPW_PARAM(minor).destnodeaddr = dest;
+ /*set node address*/
+ SPW_WRITE(&SPW_REG(minor,nodeaddr),SPW_PARAM(minor).nodeaddr);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver spacewire_console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+){
+ SPACEWIRE_DBGC(DBGSPW_IOCALLS,"open [%i,%i]\n",major, minor);
+ if ( minor >= SPACEWIRE_MAX_CORENR ) {
+ SPACEWIRE_DBG("minor %i too big\n",minor);
+ return RTEMS_INVALID_NUMBER;
+ }
+ return spacewire_hw_startup(minor);
+}
+
+rtems_device_driver spacewire_console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ SPACEWIRE_DBGC(DBGSPW_IOCALLS,"close [%i,%i]\n",major, minor);
+ spacewire_hw_stop(minor);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver spacewire_console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_libio_rw_args_t *rw_args;
+ unsigned32 count = 0;
+ rw_args = (rtems_libio_rw_args_t *) arg;
+
+ SPACEWIRE_DBGC(DBGSPW_IOCALLS,"read [%i,%i]: buf:0x%x len:%i \n",
+ major, minor, (unsigned int)rw_args->buffer,rw_args->count);
+
+ count = spacewire_hw_receive(minor,rw_args->buffer,rw_args->count);
+
+#ifdef DEBUG_SPACEWIRE_ONOFF
+ if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) {
+ int k;
+ for (k = 0;k < count;k++){
+ if (k % 16 == 0) {
+ printf ("\n");
+ }
+ printf ("%.2x(%c) ",rw_args->buffer[k] & 0xff,
+ isprint(rw_args->buffer[k] & 0xff) ? rw_args->buffer[k] & 0xff : ' ');
+ }
+ printf ("\n");
+ }
+#endif
+
+ rw_args->bytes_moved = count;
+ return RTEMS_SUCCESSFUL;
+
+}
+
+rtems_device_driver spacewire_console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_libio_rw_args_t *rw_args;
+ int count = 0;
+ rw_args = (rtems_libio_rw_args_t *) arg;
+ SPACEWIRE_DBGC(DBGSPW_IOCALLS,"write [%i,%i]: buf:0x%x len:%i\n",
+ major, minor, (unsigned int)rw_args->buffer,rw_args->count);
+
+ while (rw_args->count > 0) {
+ int c = rw_args->count;
+ if (c > SPW_PARAM(minor).txbufsize-2) {
+ c = SPW_PARAM(minor).txbufsize-2;
+ }
+ spacewire_hw_send(minor,rw_args->buffer,c);
+ rw_args->count -= c;
+ rw_args->buffer += c;
+ count += c;
+ }
+
+ if (count >= 0) {
+ rw_args->bytes_moved = count;
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+rtems_device_driver spacewire_console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
+ SPACEWIRE_DBGC(DBGSPW_IOCALLS,"ctrl [%i,%i]\n",major, minor);
+
+ if (!ioarg)
+ return RTEMS_INVALID_ADDRESS;
+
+ switch(ioarg->command) {
+ case SPACEWIRE_IOCTRL_SET_NODEADDR:
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_NODEADDR %i\n",
+ ioarg->buffer);
+ SPW_PARAM(minor).nodeaddr = (unsigned int) ioarg->buffer;
+ /*set node address*/
+ SPW_WRITE(&SPW_REG(minor,nodeaddr),SPW_PARAM(minor).nodeaddr);
+ break;
+ case SPACEWIRE_IOCTRL_SET_PROTOCOL:
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_PROTOCOL %i\n",
+ ioarg->buffer);
+ SPW_PARAM(minor).proto = (unsigned int) ioarg->buffer;
+ break;
+ case SPACEWIRE_IOCTRL_SET_DESTNODEADDR:
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DESTNODEADDR %i\n",
+ ioarg->buffer);
+ SPW_PARAM(minor).destnodeaddr = (unsigned int) ioarg->buffer;
+ break;
+ case SPACEWIRE_IOCTRL_GET_COREBASEADDR:
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_GET_BASEADDR=%i\n",
+ (unsigned int)SPW_PARAM(minor).regs);
+ *(unsigned int *)ioarg->buffer = (unsigned int )SPW_PARAM(minor).regs;
+ break;
+ case SPACEWIRE_IOCTRL_GET_COREIRQ:
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_GET_COREIRQ=%i\n",
+ (unsigned int)SPW_PARAM(minor).irq);
+ *(unsigned int *)ioarg->buffer = (unsigned int )SPW_PARAM(minor).irq;
+ break;
+#ifdef SPW_BUFMALLOC
+ case SPACEWIRE_IOCTRL_SET_PACKETSIZE:
+ {
+ spw_ioctl_packetsize *ps = (spw_ioctl_packetsize*)ioarg->buffer;
+ SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RXPACKETSIZE \n",
+ ioarg->buffer);
+ spacewire_hw_stop(minor);
+ SPW_PARAM(minor).rxbufsize = ps->rxsize;
+ SPW_PARAM(minor).txbufsize = ps->txsize;
+ SPW_PARAM(minor).rxmaxlen = SPW_PARAM(minor).rxbufsize;
+ spacewire_buffer_alloc(minor);
+ spacewire_hw_startup(minor);
+ }
+ break;
+#endif
+ case SPACEWIRE_IOCTRL_GETPACKET: {
+ spw_ioctl_packet *p = (spw_ioctl_packet*)ioarg->buffer;
+ p->ret_size = spacewire_hw_receive(minor,p->buf,p->buf_size);
+ }
+ break;
+ case SPACEWIRE_IOCTRL_PUTPACKET:{
+ spw_ioctl_packet *p = (spw_ioctl_packet*)ioarg->buffer;
+ spacewire_hw_send(minor,p->buf,p->buf_size);
+ }
+ break;
+ default:
+ return RTEMS_NOT_DEFINED;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/* ========================================================================== */
+
+int spacewire_set_rxmaxlen(int minor) {
+ unsigned int rxmax;
+ /*set rx maxlength*/
+ SPW_WRITE(&SPW_REG(minor,dma0rxmax),SPW_PARAM(minor).rxmaxlen);
+ rxmax = SPW_READ(&SPW_REG(minor,dma0rxmax));
+ if (rxmax != SPW_PARAM(minor).rxmaxlen) {
+ printf("spacewire: error initializing rx max len (0x%x, read: 0x%x)\n",
+ SPW_PARAM(minor).rxmaxlen,rxmax);
+ return 0;
+ }
+ return 1;
+}
+
+int spacewire_hw_init(int minor) {
+ unsigned int dma0ctrl;
+ int ctrl = SPW_CTRL_READ(minor);
+
+ SPW_PARAM(minor).rx = (SPACEWIRE_RXBD *)
+ SPW_ALIGN(&SPW_PARAM(minor)._rxtable,SPACEWIRE_BDTABLE_SIZE);
+ SPW_PARAM(minor).tx = (SPACEWIRE_TXBD *)
+ SPW_ALIGN(&SPW_PARAM(minor)._txtable,SPACEWIRE_BDTABLE_SIZE);
+
+ SPACEWIRE_DBG("hw_init [minor %i]\n", minor);
+
+ SPW_PARAM(minor).is_rmap = ctrl & SPACEWIRE_CTRL_RA;
+ SPW_PARAM(minor).is_rxunaligned = ctrl & SPACEWIRE_CTRL_RX;
+ SPW_PARAM(minor).is_rmapcrc = ctrl & SPACEWIRE_CTRL_RC;
+
+ /*set node address*/
+ SPW_WRITE(&SPW_REG(minor,nodeaddr),SPW_PARAM(minor).nodeaddr);
+
+ /*set clock divisor*/
+ SPW_WRITE(&SPW_REG(minor,clockdiv),SPW_PARAM(minor).clkdiv);
+ if (SPW_PARAM(minor).is_rmap) {
+ SPW_WRITE(&SPW_REG(minor,destkey),SPW_PARAM(minor).destkey);
+ }
+ SPW_WRITE(
+ &SPW_REG(minor,dma0ctrl),
+ /*clear status, set ctrl for dma chan*/
+ SPACEWIRE_DMACTRL_PS|SPACEWIRE_DMACTRL_PR|
+ SPACEWIRE_DMACTRL_TA|SPACEWIRE_DMACTRL_RA
+ );
+ if ((dma0ctrl = SPW_READ(&SPW_REG(minor,dma0ctrl))) != 0) {
+ printf("spacewire: error initializing dma ctrl (0x%x)\n",dma0ctrl);
+ }
+
+ SPW_CTRL_WRITE(minor, SPACEWIRE_CTRL_RESET ); /*set ctrl*/
+ SPW_CTRL_WRITE(minor,
+ SPACEWIRE_CTRL_LINKSTART | (SPW_PARAM(minor).maxfreq << 5)); /*set ctrl*/
+ return 0;
+}
+
+void spacewire_hw_waitlink (int minor) {
+ int j;
+ while (SPW_LINKSTATE(SPW_STATUS_READ(minor)) != 5) {
+ rtems_task_wake_after(100);
+ sched_yield();
+ printf("timeout loop dev %i\n",minor);
+ j++;
+ }
+}
+
+int spacewire_hw_startup (int minor) {
+ int i,j;
+ unsigned int dmactrl;
+ SPW_STATUS_WRITE(minor,0xFF); /*clear status*/
+ SPW_CTRL_WRITE(minor, SPACEWIRE_CTRL_RESET ); /*set ctrl*/
+ SPW_CTRL_WRITE(minor,
+ SPACEWIRE_CTRL_LINKSTART | (SPW_PARAM(minor).maxfreq << 5)); /*set ctrl*/
+ sched_yield();
+ j = 0; i = 0;
+ spacewire_hw_waitlink(minor);
+
+ /* prepare transmit buffers */
+ for (i = 0; i < SPW_PARAM(minor).txbufcnt;i++) {
+ if (i+1 == SPW_PARAM(minor).txbufcnt) {
+ SPW_PARAM(minor).tx[i].ctrl = 0|SPACEWIRE_TXBD_WR;
+ } else {
+ SPW_PARAM(minor).tx[i].ctrl = 0;
+ }
+ SPW_PARAM(minor).tx[i].addr_data =
+ ((unsigned int)&SPW_PARAM(minor).ptr_txbuf0[0]) +
+ (i * SPW_PARAM(minor).txbufsize);
+ }
+ SPW_PARAM(minor).txcur = 0;
+
+ /* prepare receive buffers */
+ for (i = 0; i < SPW_PARAM(minor).rxbufcnt;i++) {
+ if (i+1 == SPW_PARAM(minor).rxbufcnt) {
+ SPW_PARAM(minor).rx[i].ctrl = SPACEWIRE_RXBD_EN|SPACEWIRE_RXBD_WR;
+ } else {
+ SPW_PARAM(minor).rx[i].ctrl = SPACEWIRE_RXBD_EN;
+ }
+ SPW_PARAM(minor).rx[i].addr =
+ ((unsigned int)&SPW_PARAM(minor).ptr_rxbuf0[0]) +
+ (i * SPW_PARAM(minor).rxbufsize);
+ }
+ SPW_PARAM(minor).rxcur = 0;
+ SPW_PARAM(minor).rxbufcur = -1;
+ spacewire_set_rxmaxlen(minor);
+
+ SPW_WRITE(&SPW_REG(minor,dma0txdesc),(unsigned int)SPW_PARAM(minor).tx);
+ SPW_WRITE(&SPW_REG(minor,dma0rxdesc),(unsigned int)SPW_PARAM(minor).rx);
+
+ /* start RX */
+ dmactrl = SPW_READ(&SPW_REG(minor,dma0ctrl));
+ SPW_WRITE(&SPW_REG(minor,dma0ctrl),
+ (dmactrl & SPACEWIRE_PREPAREMASK_RX) |
+ SPACEWIRE_DMACTRL_RD | SPACEWIRE_DMACTRL_RXEN);
+
+ SPACEWIRE_DBGC(DBGSPW_TX,"0x%x: setup complete\n",SPW_PARAM(minor).regs);
+ return RTEMS_SUCCESSFUL;
+}
+
+int spacewire_hw_stop (int minor) {
+ unsigned int dmactrl;
+
+ /* stop RX */
+ dmactrl = SPW_READ(&SPW_REG(minor,dma0ctrl));
+ SPW_WRITE(&SPW_REG(minor,dma0ctrl),
+ (dmactrl & SPACEWIRE_PREPAREMASK_RX) &
+ ~(SPACEWIRE_DMACTRL_RD |SPACEWIRE_DMACTRL_RXEN));
+
+ /* stop link */
+ SPW_CTRL_WRITE(minor,
+ (SPW_CTRL_READ(minor) & 0x3FD) | SPACEWIRE_CTRL_LINKDISABLE);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+void spacewire_hw_send(int minor,unsigned char *b,int c) {
+
+ unsigned int dmactrl, ctrl;
+ unsigned int cur = SPW_PARAM(minor).txcur;
+ char *txb = SPW_PARAM(minor).ptr_txbuf0 + (cur * SPW_PARAM(minor).txbufsize);
+
+ sched_yield();
+ memcpy(&txb[2],b,c);
+
+ txb[0] = SPW_PARAM(minor).destnodeaddr;
+ txb[1] = SPW_PARAM(minor).proto;
+
+#ifdef DEBUG_SPACEWIRE_ONOFF
+ if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) {
+ int k;
+ for (k = 0;k < c+2;k++){
+ if (k % 16 == 0) {
+ printf ("\n");
+ }
+ printf ("%.2x(%c) ",txb[k] & 0xff,
+ isprint(txb[k] & 0xff) ? txb[k] & 0xff : ' ');
+ }
+ printf ("\n");
+ }
+#endif
+
+ do {
+ SPW_PARAM(minor).tx[0].addr_header = 0;
+ SPW_PARAM(minor).tx[0].len = c+2;
+ SPW_PARAM(minor).tx[0].addr_data = (unsigned int)txb;
+ SPW_PARAM(minor).tx[0].ctrl = SPACEWIRE_TXBD_WR|SPACEWIRE_TXBD_EN;
+
+ dmactrl = SPW_READ(&SPW_REG(minor,dma0ctrl));
+ SPW_WRITE(&SPW_REG(minor,dma0ctrl),
+ (dmactrl & SPACEWIRE_PREPAREMASK_TX) | SPACEWIRE_DMACTRL_TXEN);
+
+ while((ctrl = SPW_READ((volatile void *)&SPW_PARAM(minor).tx[0].ctrl)) &
+ SPACEWIRE_TXBD_EN) {
+ sched_yield();
+ }
+ if (ctrl & SPACEWIRE_TXBD_LE) {
+ printf("tx error: SPACEWIRE_TXBD_LE, link error\n");
+ }
+ } while(ctrl & SPACEWIRE_TXBD_ERROR);
+
+ SPACEWIRE_DBGC(DBGSPW_TX,"0x%x: transmitted <%i> bytes\n",
+ SPW_PARAM(minor).regs,c+2);
+}
+
+int spacewire_hw_receive(int minor,unsigned char *b,int c) {
+ unsigned int count = 0, len, rxlen, ctrl;
+ unsigned int cur = SPW_PARAM(minor).rxcur;
+ char *rxb = SPW_PARAM(minor).ptr_rxbuf0 + (cur * SPW_PARAM(minor).rxbufsize);
+
+ SPACEWIRE_DBGC(DBGSPW_RX,"0x%x: waitin packet at pos %i\n",
+ SPW_PARAM(minor).regs,cur);
+
+ sched_yield();
+
+ while(1) {
+ ctrl = SPW_READ((volatile void *)&SPW_PARAM(minor).rx[cur].ctrl);
+ if (!(ctrl & SPACEWIRE_RXBD_EN)) {
+ break;
+ }
+ if (SPW_LINKSTATE(SPW_STATUS_READ(minor)) != 5) {
+ return 0;
+ }
+ sched_yield();
+ }
+ SPACEWIRE_DBGC(DBGSPW_RX,"checking packet\n",0);
+
+ len = SPACEWIRE_RXBD_LENGTH(ctrl);
+ if (!(ctrl & (SPACEWIRE_RXBD_ERROR & ~SPACEWIRE_RXBD_RMAPERROR))) {
+
+ if (SPW_PARAM(minor).rxbufcur == -1) {
+ SPACEWIRE_DBGC(DBGSPW_RX,"incoming packet len %i\n",len);
+ SPW_PARAM(minor).rxbufcur = 2;
+ }
+ rxlen = len - SPW_PARAM(minor).rxbufcur;
+ if (rxlen > c) {
+ rxlen = c;
+ }
+ memcpy(b,rxb+SPW_PARAM(minor).rxbufcur,rxlen);
+ count += rxlen;
+ b += rxlen;
+ c -= rxlen;
+ SPW_PARAM(minor).rxbufcur += rxlen;
+ } else {
+ if (ctrl & SPACEWIRE_RXBD_EEP) {
+ printf("rx error: SPACEWIRE_RXBD_EEP, error end of packet\n");
+ }
+ if (ctrl & SPACEWIRE_RXBD_EHC) {
+ printf("rx error: SPACEWIRE_RXBD_EHC, header crc error\n");
+ }
+ if (ctrl & SPACEWIRE_RXBD_EDC) {
+ printf("rx error: SPACEWIRE_RXBD_EDC, crc error\n");
+ }
+ if (ctrl & SPACEWIRE_RXBD_ETR) {
+ printf("rx error: SPACEWIRE_RXBD_ETR, truncated\n");
+ }
+ }
+
+ if (SPW_PARAM(minor).rxbufcur == len ||
+ (ctrl & (SPACEWIRE_RXBD_ERROR & ~SPACEWIRE_RXBD_RMAPERROR))) {
+ spacewire_rxnext(minor);
+ }
+ return count;
+}
+
+void spacewire_rxnext(int minor) {
+
+ unsigned int dmactrl;
+ unsigned int cur = SPW_PARAM(minor).rxcur;
+ unsigned int ctrl = SPW_READ((volatile void *)&SPW_PARAM(minor).rx[cur].ctrl);
+ int cur2 = cur;
+ cur++;
+ if (cur >= SPACEWIRE_RXBUFS_NR) {
+ cur = 0;
+ ctrl |= SPACEWIRE_RXBD_WR;
+ }
+ SPW_PARAM(minor).rx[cur2].ctrl = ctrl | SPACEWIRE_RXBD_EN;
+
+ SPW_PARAM(minor).rxcur = cur;
+ SPW_PARAM(minor).rxbufcur = -1;
+
+ /* start RX */
+ dmactrl = SPW_READ(&SPW_REG(minor,dma0ctrl));
+ SPW_WRITE(&SPW_REG(minor,dma0ctrl),
+ (dmactrl & SPACEWIRE_PREPAREMASK_RX) | SPACEWIRE_DMACTRL_RD |
+ SPACEWIRE_DMACTRL_RXEN);
+
+}