📄 spacewire.c
字号:
/* * 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_ONOFFint 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...)#endifint 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -