source: rtems/bsps/sparc/shared/spw/grspw.c @ d60d303c

5
Last change on this file since d60d303c was d60d303c, checked in by Sebastian Huber <sebastian.huber@…>, on 04/20/18 at 11:33:24

bsps/sparc: Move shared files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 61.6 KB
Line 
1/*
2 *  This file contains the GRSPW SpaceWire Driver for LEON2 and LEON3.
3 *
4 *  COPYRIGHT (c) 2006
5 *  Cobham Gaisler AB.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#include <bsp.h>
13#include <rtems/libio.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <assert.h>
18#include <ctype.h>
19#include <rtems/bspIo.h>
20#include <rtems/malloc.h>
21#include <ambapp.h>
22
23#include <drvmgr/drvmgr.h>
24#include <drvmgr/ambapp_bus.h>
25#include <bsp/grspw.h>
26
27#define DBGSPW_IOCALLS 1
28#define DBGSPW_TX 2
29#define DBGSPW_RX 4
30#define DBGSPW_IOCTRL 1
31#define DBGSPW_DUMP 16
32#define DEBUG_SPACEWIRE_FLAGS (DBGSPW_IOCALLS | DBGSPW_TX | DBGSPW_RX )
33
34/* #define DEBUG_SPACEWIRE_ONOFF */
35 
36#ifdef DEBUG_SPACEWIRE_ONOFF
37#define SPACEWIRE_DBG(fmt, args...)    do { { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args); }} while(0)
38#define SPACEWIRE_DBG2(fmt)            do { { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__); }} while(0)
39#define SPACEWIRE_DBGC(c,fmt, args...) do { if (DEBUG_SPACEWIRE_FLAGS & c) { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args);  }} while(0)
40#else
41#define SPACEWIRE_DBG(fmt, args...)
42#define SPACEWIRE_DBG2(fmt, args...)
43#define SPACEWIRE_DBGC(c, fmt, args...)
44#endif
45
46typedef struct {
47   volatile unsigned int ctrl;
48   volatile unsigned int status;
49   volatile unsigned int nodeaddr;
50   volatile unsigned int clkdiv;
51   volatile unsigned int destkey;
52   volatile unsigned int time;
53   volatile unsigned int timer;
54   volatile unsigned int pad;
55   
56   volatile unsigned int dma0ctrl;
57   volatile unsigned int dma0rxmax;
58   volatile unsigned int dma0txdesc;
59   volatile unsigned int dma0rxdesc;
60   
61   /* For GRSPW core 2 and onwards */
62   volatile unsigned int dma0addr;
63   
64} LEON3_SPACEWIRE_Regs_Map;
65
66typedef struct {
67   volatile unsigned int ctrl;
68   volatile unsigned int addr;
69} SPACEWIRE_RXBD;
70
71typedef struct {
72   volatile unsigned int ctrl;
73   volatile unsigned int addr_header;
74   volatile unsigned int len;
75   volatile unsigned int addr_data;
76} SPACEWIRE_TXBD;
77
78#define SPACEWIRE_INIT_TIMEOUT 10
79#define SPACEWIRE_BDTABLE_SIZE 0x400
80#define SPACEWIRE_TXD_SIZE 1024
81#define SPACEWIRE_TXH_SIZE 64
82#define SPACEWIRE_RXPCK_SIZE 1024
83#define SPACEWIRE_TXBUFS_NR 64
84#define SPACEWIRE_RXBUFS_NR 128
85
86#define BUFMEM_PER_LINK (SPACEWIRE_TXBUFS_NR*(SPACEWIRE_TXD_SIZE+SPACEWIRE_TXH_SIZE) + SPACEWIRE_RXBUFS_NR*SPACEWIRE_RXPCK_SIZE)
87
88typedef struct {
89   /* configuration parameters */
90   struct drvmgr_dev *dev; /* Driver manager device */
91   char devName[32]; /* Device Name */
92   LEON3_SPACEWIRE_Regs_Map *regs;
93   spw_config config;
94
95   unsigned int tx_all_in_use;
96   unsigned int tx_sent;
97   unsigned int tx_cur;
98   unsigned int rxcur;
99   unsigned int rxbufcur;
100   unsigned int txdbufsize;
101   unsigned int txhbufsize;
102   unsigned int rxbufsize;
103   unsigned int txbufcnt;
104   unsigned int rxbufcnt;
105
106   /* DMA Area set by user */
107   unsigned int rx_dma_area;
108   unsigned int tx_data_dma_area;
109   unsigned int tx_hdr_dma_area;
110   unsigned int bd_dma_area;
111
112   /* statistics */
113   spw_stats stat;
114
115   unsigned int _ptr_rxbuf0;
116   char *ptr_rxbuf0;
117   char *ptr_txdbuf0;
118   char *ptr_txhbuf0;
119   char *_ptr_bd0, *ptr_bd0;
120
121   char *ptr_rxbuf0_remote;
122   char *ptr_txdbuf0_remote;
123   char *ptr_txhbuf0_remote;
124   char *ptr_bd0_remote;
125
126   unsigned int irq;
127   int minor;
128   int core_ver;
129   int open;
130   int running;
131   unsigned int core_freq_khz;
132   unsigned int rtimeout;
133
134   /* semaphores*/
135   rtems_id txsp;
136   rtems_id rxsp;
137
138   SPACEWIRE_RXBD *rx;
139   SPACEWIRE_TXBD *tx;
140
141   unsigned int rx_remote;
142   unsigned int tx_remote;
143} GRSPW_DEV;
144
145/* Function pointer called upon timecode receive */
146void (*grspw_timecode_callback)
147    (void *pDev, void *regs, int minor, unsigned int tc) = NULL;
148
149#ifdef GRSPW_DONT_BYPASS_CACHE
150#define _SPW_READ(address) (*(volatile unsigned int *)(address))
151#define _MEM_READ8(address) (*(volatile unsigned char *)(address))
152#define _MEM_READ32(address) (*(volatile unsigned int *)(address))
153#else
154static inline unsigned int _SPW_READ(volatile void *addr) {
155        unsigned int tmp;
156        __asm__ (" lda [%1]1, %0 "
157            : "=r"(tmp)
158            : "r"(addr)
159           );
160        return tmp;
161}
162
163static inline unsigned int _MEM_READ8(volatile void *addr) {
164        unsigned int tmp;
165        __asm__ (" lduba [%1]1, %0 "
166            : "=r"(tmp)
167            : "r"(addr)
168           );
169        return tmp;
170}
171
172static inline unsigned int _MEM_READ32(volatile void *addr) {
173        unsigned int tmp;
174        __asm__ (" lda [%1]1, %0 "
175            : "=r"(tmp)
176            : "r"(addr)
177           );
178        return tmp;
179}
180#endif
181
182#define MEM_READ8(addr) _MEM_READ8((volatile void *)(addr))
183#define MEM_READ32(addr) _MEM_READ32((volatile void *)(addr))
184#define SPW_READ(addr) _SPW_READ((volatile void *)(addr))
185#define SPW_WRITE(addr,v) (*(volatile unsigned int *)addr)=v
186
187#define SPW_REG(c,r) (c->regs->r)
188#define SPW_REG_CTRL(c) SPW_REG(c,ctrl)
189#define SPW_REG_STATUS(c) SPW_REG(c,status)
190#define SPW_REG_NODEADDR(c) SPW_REG(c,nodeaddr)
191
192#define SPW_CTRL_READ(c)      SPW_READ(&SPW_REG_CTRL(c))
193#define SPW_CTRL_WRITE(c,v)   SPW_WRITE(&SPW_REG_CTRL(c),v)
194#define SPW_STATUS_READ(c)    SPW_READ(&SPW_REG_STATUS(c))
195#define SPW_STATUS_WRITE(c,v) SPW_WRITE(&SPW_REG_STATUS(c),v)
196
197#define SPW_LINKSTATE(c) (((c) >> 21) & 0x7)
198
199#define SPACEWIRE_RXNR(c) ((c&~(SPACEWIRE_BDTABLE_SIZE-1))>>3)
200#define SPACEWIRE_TXNR(c) ((c&~(SPACEWIRE_BDTABLE_SIZE-1))>>4)
201
202#define SPW_RXBD_LENGTH 0x1ffffff
203#define SPW_RXBD_EN (1 << 25)
204#define SPW_RXBD_WR (1 << 26)
205#define SPW_RXBD_IE (1 << 27)
206
207#define SPW_RXBD_EEP (1 << 28)
208#define SPW_RXBD_EHC (1 << 29)
209#define SPW_RXBD_EDC (1 << 30)
210#define SPW_RXBD_ETR (1 << 31)
211
212#define SPW_RXBD_ERROR (SPW_RXBD_EEP | \
213                        SPW_RXBD_ETR)
214
215#define SPW_RXBD_RMAPERROR (SPW_RXBD_EHC | SPW_RXBD_EDC)
216
217#define SPW_TXBD_LENGTH 0xffffff
218
219#define SPW_TXBD_EN (1 << 12)
220#define SPW_TXBD_WR (1 << 13)
221#define SPW_TXBD_IE (1 << 14)
222#define SPW_TXBD_LE (1 << 15)
223#define SPW_TXBD_HC (1 << 16)
224#define SPW_TXBD_DC (1 << 17)
225
226#define SPW_TXBD_ERROR (SPW_TXBD_LE)
227
228#define SPW_CTRL_LINKDISABLED (1 << 0)
229#define SPW_CTRL_LINKSTART    (1 << 1)
230#define SPW_CTRL_AUTOSTART    (1 << 2)
231#define SPW_CTRL_IE           (1 << 3)
232#define SPW_CTRL_TI           (1 << 4)
233#define SPW_CTRL_PM           (1 << 5)
234#define SPW_CTRL_RESET        (1 << 6)
235#define SPW_CTRL_TQ           (1 << 8)
236#define SPW_CTRL_LI           (1 << 9)
237#define SPW_CTRL_TT           (1 << 10)
238#define SPW_CTRL_TR           (1 << 11)
239#define SPW_CTRL_RE           (1 << 16)
240#define SPW_CTRL_RD           (1 << 17)
241
242#define SPW_CTRL_RC           (1 << 29)
243#define SPW_CTRL_RX           (1 << 30)
244#define SPW_CTRL_RA           (1 << 31)
245
246#define SPW_STATUS_TO (1 << 0)
247#define SPW_STATUS_CE (1 << 1)
248#define SPW_STATUS_ER (1 << 2)
249#define SPW_STATUS_DE (1 << 3)
250#define SPW_STATUS_PE (1 << 4)
251#define SPW_STATUS_WE (1 << 6)
252#define SPW_STATUS_IA (1 << 7)
253#define SPW_STATUS_EE (1 << 8)
254
255#define SPW_DMACTRL_TXEN (1 << 0)
256#define SPW_DMACTRL_RXEN (1 << 1)
257#define SPW_DMACTRL_TXIE (1 << 2)
258#define SPW_DMACTRL_RXIE (1 << 3)
259#define SPW_DMACTRL_AI   (1 << 4)
260#define SPW_DMACTRL_PS   (1 << 5)
261#define SPW_DMACTRL_PR   (1 << 6)
262#define SPW_DMACTRL_TA   (1 << 7)
263#define SPW_DMACTRL_RA   (1 << 8)
264#define SPW_DMACTRL_AT   (1 << 9)
265#define SPW_DMACTRL_RX   (1 << 10)
266#define SPW_DMACTRL_RD   (1 << 11)
267#define SPW_DMACTRL_NS   (1 << 12)
268
269#define SPW_PREPAREMASK_TX (SPW_DMACTRL_RXEN | SPW_DMACTRL_RXIE | SPW_DMACTRL_PS | SPW_DMACTRL_TA | SPW_DMACTRL_RD | SPW_DMACTRL_NS)
270#define SPW_PREPAREMASK_RX (SPW_DMACTRL_TXEN | SPW_DMACTRL_TXIE | SPW_DMACTRL_AI | SPW_DMACTRL_PR | SPW_DMACTRL_RA)
271
272static int grspw_hw_init(GRSPW_DEV *pDev);
273static int grspw_hw_send(GRSPW_DEV *pDev, unsigned int hlen, char *hdr, unsigned int dlen, char *data, unsigned int options);
274static int grspw_hw_receive(GRSPW_DEV *pDev,char *b,int c);
275static int grspw_hw_startup (GRSPW_DEV *pDev, int timeout);
276static int grspw_hw_stop (GRSPW_DEV *pDev, int rx, int tx);
277static void grspw_hw_wait_rx_inactive(GRSPW_DEV *pDev);
278static int grspw_hw_waitlink (GRSPW_DEV *pDev, int timeout);
279static void grspw_hw_reset(GRSPW_DEV *pDev);
280static void grspw_hw_read_config(GRSPW_DEV *pDev);
281
282static void check_rx_errors(GRSPW_DEV *pDev, int ctrl);
283static void grspw_rxnext(GRSPW_DEV *pDev);
284static void grspw_interrupt(void *arg);
285static int grspw_buffer_alloc(GRSPW_DEV *pDev);
286
287static rtems_device_driver grspw_initialize(
288        rtems_device_major_number  major,
289        rtems_device_minor_number  minor,
290        void                    * arg
291        );
292
293static rtems_device_driver grspw_open(
294        rtems_device_major_number major,
295        rtems_device_minor_number minor,
296        void                    * arg
297        );
298
299static rtems_device_driver grspw_close(
300        rtems_device_major_number major,
301        rtems_device_minor_number minor,
302        void                    * arg
303        );
304
305static rtems_device_driver grspw_read(
306        rtems_device_major_number major,
307        rtems_device_minor_number minor,
308        void                    * arg
309        );
310
311static rtems_device_driver grspw_write(
312        rtems_device_major_number major,
313        rtems_device_minor_number minor,
314        void                    * arg
315        );
316
317static rtems_device_driver grspw_control(
318        rtems_device_major_number major,
319        rtems_device_minor_number minor,
320        void                    * arg
321        );
322
323#define GRSPW_DRIVER_TABLE_ENTRY \
324  { grspw_initialize, \
325    grspw_open, \
326    grspw_close, \
327    grspw_read, \
328    grspw_write, \
329    grspw_control }
330
331static rtems_driver_address_table grspw_driver = GRSPW_DRIVER_TABLE_ENTRY;
332static int grspw_driver_io_registered = 0;
333static rtems_device_major_number grspw_driver_io_major = 0;
334
335/******************* Driver manager interface ***********************/
336
337/* Driver prototypes */
338int grspw_register_io(rtems_device_major_number *m);
339int grspw_device_init(GRSPW_DEV *pDev);
340
341int grspw_init2(struct drvmgr_dev *dev);
342int grspw_init3(struct drvmgr_dev *dev);
343
344struct drvmgr_drv_ops grspw_ops =
345{
346        .init = {NULL,  grspw_init2, grspw_init3, NULL},
347        .remove = NULL,
348        .info = NULL
349};
350
351struct amba_dev_id grspw_ids[] =
352{
353        {VENDOR_GAISLER, GAISLER_SPW},
354        {VENDOR_GAISLER, GAISLER_SPW2},
355        {VENDOR_GAISLER, GAISLER_SPW2_DMA},
356        {0, 0}          /* Mark end of table */
357};
358
359struct amba_drv_info grspw_drv_info =
360{
361        {
362                DRVMGR_OBJ_DRV,                 /* Driver */
363                NULL,                           /* Next driver */
364                NULL,                           /* Device list */
365                DRIVER_AMBAPP_GAISLER_GRSPW_ID, /* Driver ID */
366                "GRSPW_DRV",                    /* Driver Name */
367                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
368                &grspw_ops,
369                NULL,                           /* Funcs */
370                0,                              /* No devices yet */
371                0,
372        },
373        &grspw_ids[0]
374};
375
376void grspw_register_drv (void)
377{
378        SPACEWIRE_DBG("Registering GRSPW driver\n");
379        drvmgr_drv_register(&grspw_drv_info.general);
380}
381
382int grspw_init2(struct drvmgr_dev *dev)
383{
384        GRSPW_DEV *priv;
385
386        SPACEWIRE_DBG("GRSPW[%d] on bus %s\n", dev->minor_drv,
387                dev->parent->dev->name);
388        priv = dev->priv = malloc(sizeof(GRSPW_DEV));
389        if ( !priv )
390                return DRVMGR_NOMEM;
391        memset(priv, 0, sizeof(*priv));
392        priv->dev = dev;
393
394        /* This core will not find other cores, so we wait for init2() */
395
396        return DRVMGR_OK;
397}
398
399int grspw_init3(struct drvmgr_dev *dev)
400{
401        GRSPW_DEV *priv;
402        char prefix[32];
403        rtems_status_code status;
404
405        priv = dev->priv;
406
407        /* Do initialization */
408
409        if ( grspw_driver_io_registered == 0) {
410                /* Register the I/O driver only once for all cores */
411                if ( grspw_register_io(&grspw_driver_io_major) ) {
412                        /* Failed to register I/O driver */
413                        free(dev->priv);
414                        dev->priv = NULL;
415                        return DRVMGR_FAIL;
416                }
417
418                grspw_driver_io_registered = 1;
419        }
420
421        /* I/O system registered and initialized
422         * Now we take care of device initialization.
423         */
424
425        /* Get frequency in Hz */
426        if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->core_freq_khz) ) {
427                return DRVMGR_FAIL;
428        }
429        /* Convert from Hz -> kHz */
430        priv->core_freq_khz = priv->core_freq_khz / 1000;
431
432        if ( grspw_device_init(priv) ) {
433                return DRVMGR_FAIL;
434        }
435
436        /* Get Filesystem name prefix */
437        prefix[0] = '\0';
438        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
439                /* Failed to get prefix, make sure of a unique FS name
440                 * by using the driver minor.
441                 */
442                sprintf(priv->devName, "/dev/grspw%d", dev->minor_drv);
443        } else {
444                /* Got special prefix, this means we have a bus prefix
445                 * And we should use our "bus minor"
446                 */
447                sprintf(priv->devName, "/dev/%sgrspw%d", prefix, dev->minor_bus);
448        }
449
450        /* Register Device */
451        status = rtems_io_register_name(priv->devName, grspw_driver_io_major, dev->minor_drv);
452        if (status != RTEMS_SUCCESSFUL) {
453                return DRVMGR_FAIL;
454        }
455
456        return DRVMGR_OK;
457}
458
459/******************* Driver Implementation ***********************/
460
461int grspw_register_io(rtems_device_major_number *m)
462{
463        rtems_status_code r;
464
465        if ((r = rtems_io_register_driver(0, &grspw_driver, m)) == RTEMS_SUCCESSFUL) {
466                SPACEWIRE_DBG("GRSPW driver successfully registered, major: %d\n", *m);
467        } else {
468                switch(r) {
469                case RTEMS_TOO_MANY:
470                        printk("GRSPW rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
471                        return -1;
472                case RTEMS_INVALID_NUMBER: 
473                        printk("GRSPW rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
474                        return -1;
475                case RTEMS_RESOURCE_IN_USE:
476                        printk("GRSPW rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
477                        return -1;
478                default:
479                        printk("GRSPW rtems_io_register_driver failed\n");
480                        return -1;
481                }
482        }
483        return 0;
484}
485
486int grspw_device_init(GRSPW_DEV *pDev)
487{
488        struct amba_dev_info *ambadev;
489        struct ambapp_core *pnpinfo;
490        union drvmgr_key_value *value;
491
492        /* Get device information from AMBA PnP information */
493        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
494        if ( ambadev == NULL ) {
495                return -1;
496        }
497        pnpinfo = &ambadev->info;
498        pDev->irq = pnpinfo->irq;
499        pDev->regs = (LEON3_SPACEWIRE_Regs_Map *)pnpinfo->apb_slv->start;
500        pDev->minor = pDev->dev->minor_drv;
501
502        /* Get SpaceWire core version */
503        switch( pnpinfo->device ) {
504                case GAISLER_SPW:
505                        pDev->core_ver = 1;
506                        break;
507                case GAISLER_SPW2:
508                        pDev->core_ver = 2;
509                        break;
510                case GAISLER_SPW2_DMA:
511                        pDev->core_ver = 3;
512                        break;
513                default:
514                        return -1;
515        }
516
517        /* initialize the code with some resonable values,
518         * actual initialization is done later using ioctl(fd)
519         * on the opened device */
520        pDev->config.rxmaxlen = SPACEWIRE_RXPCK_SIZE;
521        pDev->txdbufsize = SPACEWIRE_TXD_SIZE;
522        pDev->txhbufsize = SPACEWIRE_TXH_SIZE;
523        pDev->rxbufsize = SPACEWIRE_RXPCK_SIZE;
524        pDev->txbufcnt = SPACEWIRE_TXBUFS_NR;
525        pDev->rxbufcnt = SPACEWIRE_RXBUFS_NR;
526
527        pDev->_ptr_rxbuf0 = 0;
528        pDev->ptr_rxbuf0 = 0;
529        pDev->ptr_txdbuf0 = 0;
530        pDev->ptr_txhbuf0 = 0;
531        pDev->ptr_bd0 = 0;
532        pDev->rx_dma_area = 0;
533        pDev->tx_data_dma_area = 0;
534        pDev->tx_hdr_dma_area = 0;
535        pDev->bd_dma_area = 0;
536
537        /* Get Configuration from Bus resources (Let user override defaults) */
538
539        value = drvmgr_dev_key_get(pDev->dev, "txBdCnt", DRVMGR_KT_INT);
540        if ( value )
541                pDev->txbufcnt = value->i;
542
543        value = drvmgr_dev_key_get(pDev->dev, "rxBdCnt", DRVMGR_KT_INT);
544        if ( value )
545                pDev->rxbufcnt = value->i;
546
547        value = drvmgr_dev_key_get(pDev->dev, "txDataSize", DRVMGR_KT_INT);
548        if ( value )
549                pDev->txdbufsize = value->i;
550
551        value = drvmgr_dev_key_get(pDev->dev, "txHdrSize", DRVMGR_KT_INT);
552        if ( value )
553                pDev->txhbufsize = value->i;
554
555        value = drvmgr_dev_key_get(pDev->dev, "rxPktSize", DRVMGR_KT_INT);
556        if ( value ) {
557                pDev->rxbufsize = value->i;
558                pDev->config.rxmaxlen = pDev->rxbufsize;
559        }
560
561        value = drvmgr_dev_key_get(pDev->dev, "rxDmaArea", DRVMGR_KT_INT);
562        if ( value )
563                pDev->rx_dma_area = value->i;
564
565        value = drvmgr_dev_key_get(pDev->dev, "txDataDmaArea", DRVMGR_KT_INT);
566        if ( value )
567                pDev->tx_data_dma_area = value->i;
568
569        value = drvmgr_dev_key_get(pDev->dev, "txHdrDmaArea", DRVMGR_KT_INT);
570        if ( value )
571                pDev->tx_hdr_dma_area = value->i;
572
573        value = drvmgr_dev_key_get(pDev->dev, "bdDmaArea", DRVMGR_KT_INT);
574        if ( value )
575                pDev->bd_dma_area = value->i;
576
577        if (grspw_buffer_alloc(pDev))
578                return RTEMS_NO_MEMORY;
579
580        /* Create semaphores */
581        rtems_semaphore_create(
582                rtems_build_name('T', 'x', 'S', '0' + pDev->minor),
583                0,
584                RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
585                RTEMS_NO_PRIORITY_CEILING,
586                0,
587                &(pDev->txsp));
588
589        rtems_semaphore_create(
590                rtems_build_name('R', 'x', 'S', '0' + pDev->minor),
591                0,
592                RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
593                RTEMS_NO_PRIORITY_CEILING,
594                0,
595                &(pDev->rxsp));
596
597        grspw_hw_init(pDev);
598
599        return 0;
600}
601
602/* Get a value at least 6.4us in number of clock cycles */
603static unsigned int grspw_calc_timer64(int freq_khz){
604        unsigned int timer64 = (freq_khz*64+9999)/10000;
605        return timer64 & 0xfff;
606}
607
608/* Get a value at least 850ns in number of clock cycles - 3 */
609static unsigned int grspw_calc_disconnect(int freq_khz){
610        unsigned int disconnect = ((freq_khz*85+99999)/100000) - 3;
611        return disconnect & 0x3ff;
612}
613
614static int grspw_buffer_alloc(GRSPW_DEV *pDev)
615{
616        /* RX DMA AREA */
617        if (pDev->rx_dma_area & 1) {
618                /* Address given in remote address */
619                pDev->ptr_rxbuf0_remote = (char *)(pDev->rx_dma_area & ~1);
620                drvmgr_translate_check(
621                        pDev->dev,
622                        DMAMEM_TO_CPU,
623                        (void *)pDev->ptr_rxbuf0_remote,
624                        (void **)&pDev->ptr_rxbuf0,
625                        pDev->rxbufsize * pDev->rxbufcnt);
626               
627        } else {
628                if (pDev->rx_dma_area == 0) {
629                        if (pDev->_ptr_rxbuf0)
630                                free((void *)pDev->_ptr_rxbuf0);
631                        pDev->_ptr_rxbuf0 = (unsigned int) malloc(pDev->rxbufsize * pDev->rxbufcnt+4);
632                        pDev->ptr_rxbuf0 = (char *)((pDev->_ptr_rxbuf0+7)&~7);
633                        if ( !pDev->ptr_rxbuf0 )
634                                return 1;
635                } else {
636                        pDev->ptr_rxbuf0 = (char *)pDev->rx_dma_area;
637                }
638                drvmgr_translate_check(
639                        pDev->dev,
640                        CPUMEM_TO_DMA,
641                        (void *)pDev->ptr_rxbuf0,
642                        (void **)&pDev->ptr_rxbuf0_remote,
643                        pDev->rxbufsize * pDev->rxbufcnt);
644        }
645
646        /* TX-DATA DMA AREA */
647        if (pDev->tx_data_dma_area & 1) {
648                /* Address given in remote address */
649                pDev->ptr_txdbuf0_remote = (char*)(pDev->tx_data_dma_area & ~1);
650                drvmgr_translate_check(
651                        pDev->dev,
652                        DMAMEM_TO_CPU,
653                        (void *)pDev->ptr_txdbuf0_remote,
654                        (void **)&pDev->ptr_txdbuf0,
655                        pDev->txdbufsize * pDev->txbufcnt);
656        } else {
657                if (pDev->tx_data_dma_area == 0) {
658                        if (pDev->ptr_txdbuf0)
659                                free(pDev->ptr_txdbuf0);
660                        pDev->ptr_txdbuf0 = (char *) malloc(pDev->txdbufsize * pDev->txbufcnt);
661                        if (!pDev->ptr_txdbuf0)
662                                return 1;
663                } else {
664                        pDev->ptr_txdbuf0 = (char *)pDev->tx_data_dma_area;
665                }
666                drvmgr_translate_check(
667                        pDev->dev,
668                        CPUMEM_TO_DMA,
669                        (void *)pDev->ptr_txdbuf0,
670                        (void **)&pDev->ptr_txdbuf0_remote,
671                        pDev->txdbufsize * pDev->txbufcnt);
672        }
673
674        /* TX-HEADER DMA AREA */
675        if (pDev->tx_hdr_dma_area & 1) {
676                /* Address given in remote address */
677                pDev->ptr_txhbuf0_remote = (char *)(pDev->tx_hdr_dma_area & ~1);
678                drvmgr_translate_check(
679                        pDev->dev,
680                        DMAMEM_TO_CPU,
681                        (void *)pDev->ptr_txhbuf0_remote,
682                        (void **)&pDev->ptr_txhbuf0,
683                        pDev->txhbufsize * pDev->txbufcnt);
684        } else {
685                if (pDev->tx_hdr_dma_area == 0) {
686                        if (pDev->ptr_txhbuf0)
687                                free(pDev->ptr_txhbuf0);
688                        pDev->ptr_txhbuf0 = (char *) malloc(pDev->txhbufsize * pDev->txbufcnt);
689                        if (!pDev->ptr_txhbuf0)
690                                return 1;
691                } else {
692                        pDev->ptr_txhbuf0 = (char *)pDev->tx_hdr_dma_area;
693                }
694                drvmgr_translate_check(
695                        pDev->dev,
696                        CPUMEM_TO_DMA,
697                        (void *)pDev->ptr_txhbuf0,
698                        (void **)&pDev->ptr_txhbuf0_remote,
699                        pDev->txhbufsize * pDev->txbufcnt);
700        }
701
702        /* DMA DESCRIPTOR TABLES */
703        if (pDev->bd_dma_area & 1) {
704                /* Address given in remote address */
705                pDev->ptr_bd0_remote = (char *)(pDev->bd_dma_area & ~1);
706                drvmgr_translate_check(
707                        pDev->dev,
708                        DMAMEM_TO_CPU,
709                        (void *)pDev->ptr_bd0_remote,
710                        (void **)&pDev->ptr_bd0,
711                        2 * SPACEWIRE_BDTABLE_SIZE);
712        } else {
713                if (pDev->bd_dma_area == 0) {
714                        if (pDev->_ptr_bd0)
715                                free(pDev->_ptr_bd0);
716                        pDev->_ptr_bd0 =
717                                rtems_heap_allocate_aligned_with_boundary(
718                                        SPACEWIRE_BDTABLE_SIZE*2, 1024, 0);
719                        if (!pDev->_ptr_bd0)
720                                return 1;
721                        pDev->ptr_bd0 = (char *)pDev->_ptr_bd0;
722                } else {
723                        pDev->ptr_bd0 = (char *)pDev->bd_dma_area;
724                }
725                drvmgr_translate_check(
726                        pDev->dev,
727                        CPUMEM_TO_DMA,
728                        (void *)pDev->ptr_bd0,
729                        (void **)&pDev->ptr_bd0_remote,
730                        2 * SPACEWIRE_BDTABLE_SIZE);
731        }
732
733        return 0;
734}
735
736static void grspw_interrupt(void *arg)
737{
738        GRSPW_DEV *pDev = (GRSPW_DEV *)arg;
739        int dmactrl;
740        int status;
741        int ctrl;
742        unsigned int timecode;
743
744        status = SPW_STATUS_READ(pDev);
745        /*SPW_STATUS_WRITE(pDev, SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE | SPW_STATUS_TO);*/
746        SPW_STATUS_WRITE(pDev, status & (SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE));
747
748        /* Make sure to put the timecode handling first in order to get the smallest
749         * possible interrupt latency
750         */
751        if ( (status & SPW_STATUS_TO) && (grspw_timecode_callback != NULL) ) {
752            /* Timecode received. Let custom function handle this */
753            SPW_STATUS_WRITE(pDev, SPW_STATUS_TO);
754            timecode = SPW_READ(&pDev->regs->time);
755            (grspw_timecode_callback)(pDev,pDev->regs,pDev->minor,timecode);
756        }
757
758        /* Clear SPW_DMACTRL_PR if set */
759        dmactrl = SPW_READ(&pDev->regs->dma0ctrl);
760        /*SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl | SPW_DMACTRL_PR);*/
761        SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl);
762
763        /* If linkinterrupts are enabled check if it was a linkerror irq and then send an event to the
764           process set in the config */
765        if (pDev->config.link_err_irq) {
766                if (status & (SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE)) {
767                        rtems_event_send(pDev->config.event_id, SPW_LINKERR_EVENT);
768                        if (pDev->config.disable_err) {
769                                /* disable link*/
770                                SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | SPW_CTRL_LINKDISABLED);
771                                pDev->config.linkdisabled = 1;
772                                pDev->config.linkstart = 0;
773                                pDev->running = 0;
774                        }
775                }
776        }
777        if (status & SPW_STATUS_CE) {
778                pDev->stat.credit_err++;
779        }
780        if (status & SPW_STATUS_ER) {
781                pDev->stat.escape_err++;
782        }
783        if (status & SPW_STATUS_DE) {
784                pDev->stat.disconnect_err++;
785        }
786        if (status & SPW_STATUS_PE) {
787                pDev->stat.parity_err++;
788        }
789        if (status & SPW_STATUS_WE) {
790                pDev->stat.write_sync_err++;
791        }
792        if (status & SPW_STATUS_IA) {
793                pDev->stat.invalid_address++;
794        }
795        if (status & SPW_STATUS_EE) {
796                pDev->stat.early_ep++;
797        }
798
799        /* Check for tx interrupts */
800        while( (pDev->tx_sent != pDev->tx_cur) || pDev->tx_all_in_use) {
801                /* Has this descriptor been sent? */
802                ctrl = SPW_READ((volatile void *)&pDev->tx[pDev->tx_sent].ctrl);
803                if ( ctrl & SPW_TXBD_EN ) {
804                        break;
805                }
806                /* Yes, increment status counters & tx_sent so we can use this descriptor to send more packets with */
807                pDev->stat.packets_sent++;
808
809                rtems_semaphore_release(pDev->txsp);
810
811                if ( ctrl & SPW_TXBD_LE ) {
812                        pDev->stat.tx_link_err++;
813                }
814
815                /* step to next descriptor */
816                pDev->tx_sent = (pDev->tx_sent + 1) % pDev->txbufcnt;
817                pDev->tx_all_in_use = 0; /* not all of the descriptors can be in use since we just freed one. */
818        }
819
820        /* Check for rx interrupts */
821        if (dmactrl & SPW_DMACTRL_PR) {
822                rtems_semaphore_release(pDev->rxsp);
823        }
824}
825
826static rtems_device_driver grspw_initialize(
827        rtems_device_major_number major,
828        rtems_device_minor_number minor,
829        void *arg
830)
831{
832        /* Initialize device-common data structures here */
833        return RTEMS_SUCCESSFUL;
834}
835
836static rtems_device_driver grspw_open(
837        rtems_device_major_number major,
838        rtems_device_minor_number minor,
839        void * arg
840        )
841{
842        GRSPW_DEV *pDev;
843        struct drvmgr_dev *dev;
844        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "open [%i,%i]\n", major, minor);
845
846        if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) {
847                SPACEWIRE_DBG("Wrong minor %d\n", minor);
848                return RTEMS_INVALID_NAME;
849        }
850        pDev = (GRSPW_DEV *)dev->priv;
851
852        if ( pDev->open )
853                return RTEMS_RESOURCE_IN_USE;
854
855        /* Mark device open */
856        pDev->open = 1;
857
858        pDev->stat.tx_link_err = 0;
859        pDev->stat.rx_rmap_header_crc_err = 0;
860        pDev->stat.rx_rmap_data_crc_err = 0;
861        pDev->stat.rx_eep_err = 0;
862        pDev->stat.rx_truncated = 0;
863        pDev->stat.parity_err = 0;
864        pDev->stat.escape_err = 0;
865        pDev->stat.credit_err = 0;
866        pDev->stat.write_sync_err = 0;
867        pDev->stat.disconnect_err = 0;
868        pDev->stat.early_ep = 0;
869        pDev->stat.invalid_address = 0;
870        pDev->stat.packets_sent = 0;
871        pDev->stat.packets_received = 0;
872
873        pDev->config.rm_prot_id = 0;
874        pDev->config.keep_source = 0;
875        pDev->config.check_rmap_err = 0;
876        pDev->config.tx_blocking = 0;
877        pDev->config.tx_block_on_full = 0;
878        pDev->config.rx_blocking = 0;
879        pDev->config.disable_err = 0;
880        pDev->config.link_err_irq = 0;
881        pDev->config.event_id = 0;
882        pDev->config.rtimeout = 0;
883
884        pDev->running = 0;
885        pDev->core_freq_khz = 0;
886
887        /* Reset Core */
888        grspw_hw_reset(pDev);
889
890        /* Read default configuration */
891        grspw_hw_read_config(pDev);
892
893        return RTEMS_SUCCESSFUL;
894}
895
896static rtems_device_driver grspw_close(
897        rtems_device_major_number major,
898        rtems_device_minor_number minor,
899        void * arg
900        )
901{       
902        GRSPW_DEV *pDev;
903        struct drvmgr_dev *dev;
904
905        if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) {
906                return RTEMS_INVALID_NAME;
907        }
908        pDev = (GRSPW_DEV *)dev->priv;
909
910        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "close [%i,%i]\n", major, minor);       
911        rtems_semaphore_delete(pDev->txsp);
912        rtems_semaphore_delete(pDev->rxsp);
913
914        grspw_hw_stop(pDev,1,1);
915
916        grspw_hw_reset(pDev);
917
918        /* Mark device closed - not open */
919        pDev->open = 0;
920
921        return RTEMS_SUCCESSFUL;
922}
923
924static rtems_device_driver grspw_read(
925        rtems_device_major_number major,
926        rtems_device_minor_number minor,
927        void                * arg
928        )
929{
930        rtems_libio_rw_args_t *rw_args;
931        unsigned int count = 0;
932        GRSPW_DEV *pDev;
933        struct drvmgr_dev *dev;
934        int status;
935
936        if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) {
937                return RTEMS_INVALID_NAME;
938        }
939        pDev = (GRSPW_DEV *)dev->priv;
940
941        rw_args = (rtems_libio_rw_args_t *) arg;
942
943        /* is link up? */
944        if ( !pDev->running ) {
945                return RTEMS_INVALID_NAME;
946        }
947
948        if ((rw_args->count < 1) || (rw_args->buffer == NULL)) {
949                return RTEMS_INVALID_NAME;
950        }
951
952        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "read  [%i,%i]: buf:0x%x len:%i \n", major, minor, (unsigned int)rw_args->buffer, rw_args->count);
953
954        while ( (count = grspw_hw_receive(pDev, rw_args->buffer, rw_args->count)) == 0) {
955                /* wait a moment for any descriptors to get available
956                 *
957                 * Semaphore is signaled by interrupt handler
958                 */
959                if (pDev->config.rx_blocking) {
960                        SPACEWIRE_DBG2("Rx blocking\n");
961                        if ( pDev->config.rtimeout ) {
962                                status = rtems_semaphore_obtain(pDev->rxsp, RTEMS_WAIT, pDev->config.rtimeout);
963                                if ( status == RTEMS_TIMEOUT )
964                                        return RTEMS_TIMEOUT;
965                        } else {
966                                rtems_semaphore_obtain(pDev->rxsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
967                        }
968                } else {
969                        SPACEWIRE_DBG2("Rx non blocking\n");
970                        return RTEMS_RESOURCE_IN_USE;
971                }
972        }
973
974#ifdef DEBUG_SPACEWIRE_ONOFF 
975        if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) {
976                int k;
977                for (k = 0; k < count; k++){
978                        if (k % 16 == 0) {
979                                printf ("\n");
980                        }
981                        printf ("%.2x(%c) ", rw_args->buffer[k] & 0xff, isprint(rw_args->buffer[k] & 0xff) ? rw_args->buffer[k] & 0xff : ' ');
982                }
983                printf ("\n");
984        }
985#endif
986
987        rw_args->bytes_moved = count;
988        return RTEMS_SUCCESSFUL;
989}
990
991static rtems_device_driver grspw_write(
992        rtems_device_major_number major,
993        rtems_device_minor_number minor,
994        void                * arg
995)
996{
997        rtems_libio_rw_args_t *rw_args;
998        GRSPW_DEV *pDev;
999        struct drvmgr_dev *dev;
1000
1001        if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) {
1002                return RTEMS_INVALID_NAME;
1003        }
1004        pDev = (GRSPW_DEV *)dev->priv;
1005
1006        rw_args = (rtems_libio_rw_args_t *) arg;
1007        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "write [%i,%i]: buf:0x%x len:%i\n", major, minor, (unsigned int)rw_args->buffer, rw_args->count);
1008
1009        /* is link up? */
1010        if ( !pDev->running ) {
1011                return RTEMS_INVALID_NAME;
1012        }
1013
1014        if ((rw_args->count > pDev->txdbufsize) || (rw_args->count < 1) || (rw_args->buffer == NULL)) {
1015                return RTEMS_INVALID_NAME;
1016        }
1017
1018        while ((rw_args->bytes_moved = grspw_hw_send(pDev, 0, NULL, rw_args->count, rw_args->buffer, 0)) == 0) {
1019                if (pDev->config.tx_block_on_full == 1) {
1020                        SPACEWIRE_DBG2("Tx Block on full \n");
1021                        rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1022                } else {
1023                        SPACEWIRE_DBG2("Tx non blocking return when full \n");
1024                        return RTEMS_RESOURCE_IN_USE;
1025                }
1026        }
1027        return RTEMS_SUCCESSFUL;
1028}
1029
1030static rtems_device_driver grspw_control(
1031        rtems_device_major_number major,
1032        rtems_device_minor_number minor,
1033        void                * arg
1034        )
1035{
1036        spw_ioctl_pkt_send *args;
1037        spw_ioctl_packetsize *ps;
1038        int status;
1039        unsigned int tmp,mask,nodeaddr,nodemask;
1040        int timeout;
1041        rtems_device_driver ret;
1042        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1043        GRSPW_DEV *pDev;
1044        struct drvmgr_dev *dev;
1045
1046        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "ctrl [%i,%i]\n", major, minor);
1047
1048        if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) {
1049                return RTEMS_INVALID_NAME;
1050        }
1051        pDev = (GRSPW_DEV *)dev->priv;
1052
1053        if (!ioarg)
1054                return RTEMS_INVALID_NAME;
1055
1056        ioarg->ioctl_return = 0;
1057        switch(ioarg->command) {
1058                case SPACEWIRE_IOCTRL_SET_NODEADDR:
1059                        /*set node address*/
1060                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEADDR %i\n",(unsigned int)ioarg->buffer);
1061                        if ((unsigned int)ioarg->buffer > 255) {
1062                                return RTEMS_INVALID_NAME;
1063                        }
1064                        nodeaddr = ((unsigned int)ioarg->buffer) & 0xff;
1065                        tmp = SPW_READ(&pDev->regs->nodeaddr);
1066                        tmp &= 0xffffff00; /* Remove old address */
1067                        tmp |= nodeaddr;
1068                        SPW_WRITE(&pDev->regs->nodeaddr, tmp);
1069                        if ((SPW_READ(&pDev->regs->nodeaddr)&0xff) != nodeaddr) {
1070                                return RTEMS_IO_ERROR;
1071                        }
1072                        pDev->config.nodeaddr = nodeaddr;
1073                        break;
1074                case SPACEWIRE_IOCTRL_SET_NODEMASK:
1075                        /*set node address*/
1076                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEMASK %i\n",(unsigned int)ioarg->buffer);
1077                        if ( pDev->core_ver > 1 ){
1078                                if ((unsigned int)ioarg->buffer > 255) {
1079                                        return RTEMS_INVALID_NAME;
1080                                }
1081                                nodemask = ((unsigned int)ioarg->buffer) & 0xff;
1082                                tmp = SPW_READ(&pDev->regs->nodeaddr);
1083                                tmp &= 0xffff00ff; /* Remove old mask */
1084                                tmp |= nodemask<<8;
1085                                SPW_WRITE(&pDev->regs->nodeaddr, tmp);
1086                                if (((SPW_READ(&pDev->regs->nodeaddr)>>8)&0xff) != nodemask) {
1087                                        return RTEMS_IO_ERROR;
1088                                }
1089                                pDev->config.nodemask = nodemask;
1090                        }else{
1091                                SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_NODEMASK: not implemented in GRSPW1 HW\n");
1092                        }
1093                        break;
1094                case SPACEWIRE_IOCTRL_SET_RXBLOCK:
1095                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_RXBLOCK %i \n", (unsigned int)ioarg->buffer);
1096                        if ((unsigned int)ioarg->buffer > 1) {
1097                                return RTEMS_INVALID_NAME;
1098                        }
1099                        pDev->config.rx_blocking = (unsigned int)ioarg->buffer;
1100                        break;
1101                case SPACEWIRE_IOCTRL_SET_DESTKEY:
1102                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DESTKEY %i\n", (unsigned int)ioarg->buffer);
1103                        if (!pDev->config.is_rmap) {
1104                                return RTEMS_NOT_IMPLEMENTED;
1105                        }
1106                        if ((unsigned int)ioarg->buffer > 255) {
1107                                return RTEMS_INVALID_NAME;
1108                        }
1109                        SPW_WRITE(&pDev->regs->destkey, (unsigned int)ioarg->buffer);
1110                        if (SPW_READ(&pDev->regs->destkey) != (unsigned int)ioarg->buffer) {
1111                                return RTEMS_IO_ERROR;
1112                        }
1113                        pDev->config.destkey = (unsigned int)ioarg->buffer;
1114                        break;
1115                case SPACEWIRE_IOCTRL_SET_CLKDIV:
1116                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CLKDIV %i\n", (unsigned int)ioarg->buffer);
1117                        if ((unsigned int)ioarg->buffer > 255) {
1118                                return RTEMS_INVALID_NAME;
1119                        }
1120                        if ( pDev->core_ver == 3 )
1121                                break;
1122                        tmp = SPW_READ(&pDev->regs->clkdiv);
1123                        tmp &= ~0xff; /* Remove old Clockdiv Setting */
1124                        tmp |= ((unsigned int)ioarg->buffer) & 0xff; /* add new clockdiv setting */
1125                        SPW_WRITE(&pDev->regs->clkdiv, tmp);
1126                        if (SPW_READ(&pDev->regs->clkdiv) != tmp) {
1127                                return RTEMS_IO_ERROR;
1128                        }
1129                        pDev->config.clkdiv = tmp;
1130                        break;
1131                case SPACEWIRE_IOCTRL_SET_CLKDIVSTART:
1132                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CLKDIVSTART %i\n", (unsigned int)ioarg->buffer);
1133                        if ((unsigned int)ioarg->buffer > 255) {
1134                                return RTEMS_INVALID_NAME;
1135                        }
1136                        if ( pDev->core_ver == 3 )
1137                                break;
1138                        tmp = SPW_READ(&pDev->regs->clkdiv);
1139                        tmp &= ~0xff00; /* Remove old Clockdiv Start Setting */
1140                        tmp |= (((unsigned int)ioarg->buffer) & 0xff)<<8; /* add new clockdiv start setting */
1141                        SPW_WRITE(&pDev->regs->clkdiv, tmp);
1142                        if (SPW_READ(&pDev->regs->clkdiv) != tmp) {
1143                                return RTEMS_IO_ERROR;
1144                        }
1145                        pDev->config.clkdiv = tmp;
1146                        break;                 
1147                case SPACEWIRE_IOCTRL_SET_TIMER:
1148                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_TIMER %i\n", (unsigned int)ioarg->buffer);
1149                        if ( pDev->core_ver <= 1 ) {
1150                                if ((unsigned int)ioarg->buffer > 4095) {
1151                                        return RTEMS_INVALID_NAME;
1152                                }
1153                                SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFFFF000) | ((unsigned int)ioarg->buffer & 0xFFF));
1154                                if ((SPW_READ(&pDev->regs->timer) & 0xFFF) != (unsigned int)ioarg->buffer) {
1155                                        return RTEMS_IO_ERROR;
1156                                }
1157                                pDev->config.timer = (unsigned int)ioarg->buffer;
1158                        }else{
1159                                SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_TIMER: removed in GRSPW2 HW\n");
1160                        }
1161                        break;
1162                case SPACEWIRE_IOCTRL_SET_DISCONNECT:
1163                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DISCONNECT %i\n", (unsigned int)ioarg->buffer);
1164                        if ( pDev->core_ver <= 1 ) {
1165                                if ((unsigned int)ioarg->buffer > 1023) {
1166                                        return RTEMS_INVALID_NAME;
1167                                }
1168                                SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFC00FFF) | (((unsigned int)ioarg->buffer & 0x3FF) << 12));
1169                                if (((SPW_READ(&pDev->regs->timer) >> 12) & 0x3FF) != (unsigned int)ioarg->buffer) {
1170                                        return RTEMS_IO_ERROR;
1171                                }
1172                                pDev->config.disconnect = (unsigned int)ioarg->buffer;
1173                        }else{
1174                                SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_DISCONNECT: not implemented for GRSPW2\n");
1175                        }
1176                        break;
1177                case SPACEWIRE_IOCTRL_SET_PROMISCUOUS: 
1178                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_PROMISCUOUS %i \n", (unsigned int)ioarg->buffer);
1179                        if ((unsigned int)ioarg->buffer > 1) {
1180                                return RTEMS_INVALID_NAME;
1181                        }
1182                        SPW_CTRL_WRITE(pDev, SPW_CTRL_READ(pDev) | ((unsigned int)ioarg->buffer << 5));
1183                        if (((SPW_CTRL_READ(pDev) >> 5) & 1) != (unsigned int)ioarg->buffer) {
1184                                return RTEMS_IO_ERROR;
1185                        }
1186                        pDev->config.promiscuous = (unsigned int)ioarg->buffer;
1187                        break;
1188                case SPACEWIRE_IOCTRL_SET_RMAPEN:
1189                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RMAPEN %i \n", (unsigned int)ioarg->buffer);
1190                        if ((unsigned int)ioarg->buffer > 1) {
1191                                return RTEMS_INVALID_NAME;
1192                        }
1193                        SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFEFFFF) | ((unsigned int)ioarg->buffer << 16));
1194                        if (((SPW_CTRL_READ(pDev) >> 16) & 1) != (unsigned int)ioarg->buffer) {
1195                                return RTEMS_IO_ERROR;
1196                        }
1197                        pDev->config.rmapen = (unsigned int)ioarg->buffer;
1198                        break;
1199                case SPACEWIRE_IOCTRL_SET_RMAPBUFDIS:
1200                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RMAPBUFDIS %i \n", (unsigned int)ioarg->buffer);
1201                        if ((unsigned int)ioarg->buffer > 1) {
1202                                return RTEMS_INVALID_NAME;
1203                        }
1204                        SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFDFFFF) | ((unsigned int)ioarg->buffer << 17));
1205                        if (((SPW_CTRL_READ(pDev) >> 17) & 1) != (unsigned int)ioarg->buffer) {
1206                                return RTEMS_IO_ERROR;
1207                        }
1208                        pDev->config.rmapbufdis = (unsigned int)ioarg->buffer;
1209                        break;
1210                case SPACEWIRE_IOCTRL_SET_CHECK_RMAP:
1211                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CHECK_RMAP %i \n", (unsigned int)ioarg->buffer);
1212                        if ((unsigned int)ioarg->buffer > 1) {
1213                                return RTEMS_INVALID_NAME;
1214                        }
1215                        pDev->config.check_rmap_err = (unsigned int)ioarg->buffer;
1216                        break;
1217                case SPACEWIRE_IOCTRL_SET_RM_PROT_ID:
1218                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_RM_PROT_ID %i \n", (unsigned int)ioarg->buffer);
1219                        if ((unsigned int)ioarg->buffer > 1) {
1220                                return RTEMS_INVALID_NAME;
1221                        }
1222                        pDev->config.rm_prot_id = (unsigned int)ioarg->buffer;
1223                        break;
1224                case SPACEWIRE_IOCTRL_SET_KEEP_SOURCE:
1225                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_KEEP_SOURCE %i \n", (unsigned int)ioarg->buffer);
1226                        if ((unsigned int)ioarg->buffer > 1) {
1227                                return RTEMS_INVALID_NAME;
1228                        }
1229                        pDev->config.keep_source = (unsigned int)ioarg->buffer;
1230                        break;
1231                case SPACEWIRE_IOCTRL_SET_TXBLOCK:
1232                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_TXBLOCK %i \n", (unsigned int)ioarg->buffer);
1233                        if ((unsigned int)ioarg->buffer > 1) {
1234                                return RTEMS_INVALID_NAME;
1235                        }
1236                        pDev->config.tx_blocking = (unsigned int)ioarg->buffer;
1237                        break;
1238                case SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL:
1239                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL %i \n", (unsigned int)ioarg->buffer);
1240                        if ((unsigned int)ioarg->buffer > 1) {
1241                                return RTEMS_INVALID_NAME;
1242                        }
1243                        pDev->config.tx_block_on_full = (unsigned int)ioarg->buffer;
1244                        break; 
1245                case SPACEWIRE_IOCTRL_SET_DISABLE_ERR:
1246                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_DISABLE_ERR %i \n", (unsigned int)ioarg->buffer);
1247                        if ((unsigned int)ioarg->buffer > 1) {
1248                                return RTEMS_INVALID_NAME;
1249                        }
1250                        pDev->config.disable_err = (unsigned int)ioarg->buffer;
1251                        break;
1252                case SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ:
1253                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ %i \n", (unsigned int)ioarg->buffer);
1254                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "CTRL REG: %x\n", SPW_CTRL_READ(pDev));
1255                        if ((unsigned int)ioarg->buffer > 1) {
1256                                return RTEMS_INVALID_NAME;
1257                        }
1258                        tmp = (SPW_CTRL_READ(pDev) & 0xFFFFFDF7) | ((unsigned int)ioarg->buffer << 9);
1259                        if (tmp & (SPW_CTRL_LI|SPW_CTRL_TQ))
1260                                tmp |= SPW_CTRL_IE;
1261                        SPW_CTRL_WRITE(pDev, tmp);
1262                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "CTRL REG: %x\n", SPW_CTRL_READ(pDev));
1263                        if (((SPW_CTRL_READ(pDev) >> 9) & 1) != (unsigned int)ioarg->buffer) {
1264                                return RTEMS_IO_ERROR;
1265                        }
1266                        pDev->config.link_err_irq = (unsigned int)ioarg->buffer;
1267                        break;
1268                case SPACEWIRE_IOCTRL_SET_EVENT_ID:
1269                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_EVENT_ID %i \n", (unsigned int)ioarg->buffer);
1270                        pDev->config.event_id = (rtems_id)ioarg->buffer;
1271                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "Event id: %i\n", pDev->config.event_id);
1272                        break;
1273
1274                /* Change MAX Packet size by:
1275                 *  - stop RX/TX (if on)
1276                 *  - wait for hw to complete RX DMA (if on)
1277                 *  - reallocate buffers with new size
1278                 *  - tell hw about new size & start RX/TX again (if previously on)
1279                 */
1280                case SPACEWIRE_IOCTRL_SET_PACKETSIZE:
1281                        if (ioarg->buffer == NULL)
1282                                return RTEMS_INVALID_NAME;
1283                        ps = (spw_ioctl_packetsize*) ioarg->buffer;
1284                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RXPACKETSIZE %i \n", (unsigned int)ioarg->buffer);
1285
1286                        tmp = pDev->running;
1287
1288                        if ( pDev->running ){
1289                                /* Stop RX */
1290                                grspw_hw_stop(pDev,1,1);
1291
1292                                /* If packetsize fails it is good to know if in running mode */
1293                                pDev->running = 0;
1294
1295                                /* Wait for Receiver to finnish pending DMA transfers if any */
1296                                grspw_hw_wait_rx_inactive(pDev);
1297                        }
1298
1299                        /* Save new buffer sizes */
1300                        pDev->rxbufsize = ((ps->rxsize+7)&~7);
1301                        pDev->txdbufsize = ps->txdsize;
1302                        pDev->txhbufsize = ps->txhsize;
1303                        pDev->config.rxmaxlen = pDev->rxbufsize;
1304
1305                        /* Free previous buffers & allocate buffers with new size */
1306                        if (grspw_buffer_alloc(pDev))
1307                                return RTEMS_NO_MEMORY;
1308
1309                        /* if RX was actived before, we reactive it again */
1310                        if ( tmp ) {
1311                                if ( (status = grspw_hw_startup(pDev,-1)) != RTEMS_SUCCESSFUL ) {
1312                                        return status;
1313                                }
1314                                pDev->running = 1;
1315                        }
1316#if 0
1317                        /* Rewrite previous config which was wasted due to reset in hw_startup */
1318                        SPW_WRITE(&pDev->regs->nodeaddr, pDev->config.nodeaddr);
1319                        SPW_WRITE(&pDev->regs->destkey, pDev->config.destkey);
1320                        SPW_WRITE(&pDev->regs->clkdiv, pDev->config.clkdiv);
1321                        SPW_WRITE(&pDev->regs->timer, pDev->config.timer | ( (pDev->config.disconnect & 0x3FF) << 12) );
1322                        SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & !(SPW_CTRL_LINKSTART | SPW_CTRL_PM | SPW_CTRL_RE | SPW_CTRL_RD | SPW_CTRL_TT | SPW_CTRL_TR)) | \
1323                                              (pDev->config.promiscuous << 5) | (pDev->config.rmapen << 16) | (pDev->config.rmapbufdis << 17) | \
1324                                              (pDev->config.linkdisabled) | (pDev->config.linkstart << 1));
1325#endif
1326                        break;
1327                case SPACEWIRE_IOCTRL_GET_CONFIG:
1328                        if (ioarg->buffer == NULL)
1329                                return RTEMS_INVALID_NAME;
1330                        SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_GET_CONFIG \n");
1331                        (*(spw_config *)ioarg->buffer).nodeaddr = pDev->config.nodeaddr;
1332                        (*(spw_config *)ioarg->buffer).nodemask = pDev->config.nodemask;
1333                        (*(spw_config *)ioarg->buffer).destkey = pDev->config.destkey;
1334                        (*(spw_config *)ioarg->buffer).clkdiv = pDev->config.clkdiv;
1335                        (*(spw_config *)ioarg->buffer).rxmaxlen = pDev->config.rxmaxlen;
1336                        (*(spw_config *)ioarg->buffer).timer = pDev->config.timer;
1337                        (*(spw_config *)ioarg->buffer).disconnect = pDev->config.disconnect;
1338                        (*(spw_config *)ioarg->buffer).promiscuous = pDev->config.promiscuous;
1339                        (*(spw_config *)ioarg->buffer).rmapen = pDev->config.rmapen;
1340                        (*(spw_config *)ioarg->buffer).rmapbufdis = pDev->config.rmapbufdis;
1341                        (*(spw_config *)ioarg->buffer).check_rmap_err = pDev->config.check_rmap_err;
1342                        (*(spw_config *)ioarg->buffer).rm_prot_id = pDev->config.rm_prot_id;
1343                        (*(spw_config *)ioarg->buffer).tx_blocking = pDev->config.tx_blocking;
1344                        (*(spw_config *)ioarg->buffer).disable_err = pDev->config.disable_err;
1345                        (*(spw_config *)ioarg->buffer).link_err_irq = pDev->config.link_err_irq;
1346                        (*(spw_config *)ioarg->buffer).event_id = pDev->config.event_id;
1347                        (*(spw_config *)ioarg->buffer).is_rmap = pDev->config.is_rmap;
1348                        (*(spw_config *)ioarg->buffer).is_rmapcrc = pDev->config.is_rmapcrc;
1349                        (*(spw_config *)ioarg->buffer).is_rxunaligned = pDev->config.is_rxunaligned;
1350                        (*(spw_config *)ioarg->buffer).linkdisabled = pDev->config.linkdisabled;
1351                        (*(spw_config *)ioarg->buffer).linkstart = pDev->config.linkstart;
1352                        (*(spw_config *)ioarg->buffer).rx_blocking = pDev->config.rx_blocking;
1353                        (*(spw_config *)ioarg->buffer).tx_block_on_full = pDev->config.tx_block_on_full;
1354                        (*(spw_config *)ioarg->buffer).keep_source = pDev->config.keep_source;
1355                        (*(spw_config *)ioarg->buffer).rtimeout = pDev->config.rtimeout;
1356                        break;
1357                case SPACEWIRE_IOCTRL_GET_LINK_STATUS:
1358                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_GET_STATUS=%i \n", (unsigned int)((SPW_STATUS_READ(pDev) >> 21) & 0x7));
1359                        *(unsigned int *)ioarg->buffer = (unsigned int )((SPW_STATUS_READ(pDev) >> 21) & 0x7);
1360                        break;
1361                case SPACEWIRE_IOCTRL_GET_STATISTICS:
1362                        if (ioarg->buffer == NULL)
1363                                return RTEMS_INVALID_NAME;
1364                        SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_GET_STATISTICS \n");
1365                        (*(spw_stats *)ioarg->buffer).tx_link_err = pDev->stat.tx_link_err;
1366                        (*(spw_stats *)ioarg->buffer).rx_rmap_header_crc_err = pDev->stat.rx_rmap_header_crc_err;
1367                        (*(spw_stats *)ioarg->buffer).rx_rmap_data_crc_err = pDev->stat.rx_rmap_data_crc_err;
1368                        (*(spw_stats *)ioarg->buffer).rx_eep_err =  pDev->stat.rx_eep_err;
1369                        (*(spw_stats *)ioarg->buffer).rx_truncated = pDev->stat.rx_truncated;
1370                        (*(spw_stats *)ioarg->buffer).parity_err = pDev->stat.parity_err;
1371                        (*(spw_stats *)ioarg->buffer).escape_err = pDev->stat.escape_err;
1372                        (*(spw_stats *)ioarg->buffer).credit_err = pDev->stat.credit_err;
1373                        (*(spw_stats *)ioarg->buffer).write_sync_err = pDev->stat.write_sync_err;
1374                        (*(spw_stats *)ioarg->buffer).disconnect_err = pDev->stat.disconnect_err;
1375                        (*(spw_stats *)ioarg->buffer).early_ep = pDev->stat.early_ep;
1376                        (*(spw_stats *)ioarg->buffer).invalid_address = pDev->stat.invalid_address;
1377                        (*(spw_stats *)ioarg->buffer).packets_sent = pDev->stat.packets_sent;
1378                        (*(spw_stats *)ioarg->buffer).packets_received = pDev->stat.packets_received;
1379                        break;
1380                case SPACEWIRE_IOCTRL_CLR_STATISTICS:
1381                        SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_CLR_STATISTICS \n");
1382                        pDev->stat.tx_link_err = 0;
1383                        pDev->stat.rx_rmap_header_crc_err = 0;
1384                        pDev->stat.rx_rmap_data_crc_err = 0;
1385                        pDev->stat.rx_eep_err = 0;
1386                        pDev->stat.rx_truncated = 0;
1387                        pDev->stat.parity_err = 0;
1388                        pDev->stat.escape_err = 0;
1389                        pDev->stat.credit_err = 0;
1390                        pDev->stat.write_sync_err = 0;
1391                        pDev->stat.disconnect_err = 0;
1392                        pDev->stat.early_ep = 0;
1393                        pDev->stat.invalid_address = 0;
1394                        pDev->stat.packets_sent = 0;
1395                        pDev->stat.packets_received = 0;
1396                        break;
1397                case SPACEWIRE_IOCTRL_SEND:
1398                        if (ioarg->buffer == NULL)
1399                                return RTEMS_INVALID_NAME;
1400                        args = (spw_ioctl_pkt_send *)ioarg->buffer;
1401                        args->sent = 0;
1402
1403                        /* is link up? */
1404                        if ( !pDev->running ) {
1405                                return RTEMS_INVALID_NAME;
1406                        }
1407       
1408                        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "write [%i,%i]: hlen: %i hbuf:0x%x dlen:%i dbuf:0x%x\n", major, minor,
1409                                       (unsigned int)args->hlen, (int)args->hdr,(unsigned int)args->dlen, (int)args->data);
1410                       
1411                        if ((args->hlen > pDev->txhbufsize) || (args->dlen > pDev->txdbufsize) ||
1412                            ((args->hlen+args->dlen) < 1) ||
1413                            ((args->hdr == NULL) && (args->hlen != 0)) || ((args->data == NULL) && (args->dlen != 0))) {
1414                                return RTEMS_INVALID_NAME;
1415                        }
1416                        while ((args->sent = grspw_hw_send(pDev, args->hlen, args->hdr, args->dlen, args->data, args->options)) == 0) {
1417                                if (pDev->config.tx_block_on_full == 1) {
1418                                        SPACEWIRE_DBG2("Tx Block on full \n");
1419                                        rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1420                                } else {
1421                                        SPACEWIRE_DBG2("Tx non blocking return when full \n");
1422                                        return RTEMS_RESOURCE_IN_USE;
1423                                }
1424                        }
1425                        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "Tx ioctl return: %i  \n", args->sent);
1426                        break;
1427
1428                case SPACEWIRE_IOCTRL_LINKDISABLE:
1429                        pDev->config.linkdisabled = 1;
1430                        pDev->config.linkstart = 0;
1431                        if ( pDev->core_ver != 3 ) {
1432                                SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | 1);
1433                                if ((SPW_CTRL_READ(pDev) & 3) != 1) {
1434                                        return RTEMS_IO_ERROR;
1435                                }
1436                        }
1437                        break;
1438
1439                case SPACEWIRE_IOCTRL_LINKSTART:
1440                        pDev->config.linkdisabled = 0;
1441                        pDev->config.linkstart = 1;
1442                        if ( pDev->core_ver != 3 ) {
1443                                SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | 2);
1444                                if ((SPW_CTRL_READ(pDev) & 3) != 2) {
1445                                        return RTEMS_IO_ERROR;
1446                                }
1447                        }
1448                        break;
1449
1450                /* Calculate timer register from GRSPW Core frequency
1451                 * Also possible to set disconnect and timer64 from
1452                 *  - SPACEWIRE_IOCTRL_SET_DISCONNECT
1453                 *  - SPACEWIRE_IOCTRL_SET_TIMER
1454                 */
1455                case SPACEWIRE_IOCTRL_SET_COREFREQ:
1456                        pDev->core_freq_khz = (unsigned int)ioarg->buffer;
1457                        if ( pDev->core_freq_khz == 0 ){
1458                                /* Get GRSPW clock frequency from system clock.
1459                                 * System clock has been read from timer inited
1460                                 * by RTEMS loader (mkprom)
1461                                 */
1462                                drvmgr_freq_get(pDev->dev, DEV_APB_SLV,
1463                                        &pDev->core_freq_khz);
1464                                /* Convert from Hz -> kHz */
1465                                pDev->core_freq_khz = pDev->core_freq_khz / 1000;
1466                        }
1467
1468                        /* Only GRSPW1 needs the Timer64 and Disconnect values
1469                         * GRSPW2 and onwards doesn't have this register.
1470                         */
1471                        if ( pDev->core_ver <= 1 ){
1472                                /* Calculate Timer64 & Disconnect */
1473                                pDev->config.timer = grspw_calc_timer64(pDev->core_freq_khz);
1474                                pDev->config.disconnect = grspw_calc_disconnect(pDev->core_freq_khz);
1475
1476                                /* Set Timer64 & Disconnect Register */
1477                                SPW_WRITE(&pDev->regs->timer,
1478                                (SPW_READ(&pDev->regs->timer) & 0xFFC00000) |
1479                                ((pDev->config.disconnect & 0x3FF)<<12) |
1480                                (pDev->config.timer & 0xFFF));
1481
1482                                /* Check that the registers were written successfully */
1483                                tmp = SPW_READ(&pDev->regs->timer) & 0x003fffff;
1484                                if ( ((tmp & 0xFFF) != pDev->config.timer) ||
1485                                     (((tmp >> 12) & 0x3FF) != pDev->config.disconnect) ) {
1486                                        return RTEMS_IO_ERROR;
1487                                }
1488                        }
1489                        break;
1490
1491                case SPACEWIRE_IOCTRL_START:
1492                        if ( pDev->running ){
1493                                return RTEMS_INVALID_NAME;
1494                        }
1495
1496                        /* Get timeout from userspace
1497                         *  timeout:
1498                         *   €  -1         = Default timeout
1499                         *   €  less than -1 = forever
1500                         *   €  0           = no wait, proceed if link is up
1501                         *   €  positive     = specifies number of system clock ticks that
1502                         *                   startup will wait for link to enter ready mode.
1503                         */
1504                        timeout = (int)ioarg->buffer;
1505                       
1506                        if ( (ret=grspw_hw_startup(pDev,timeout)) != RTEMS_SUCCESSFUL ) {
1507                                return ret;
1508                        }
1509                        pDev->running = 1;
1510                        /* Register interrupt routine and unmask IRQ */
1511                        drvmgr_interrupt_register(pDev->dev, 0, "grspw", grspw_interrupt, pDev);
1512
1513                        break;
1514
1515                case SPACEWIRE_IOCTRL_STOP:
1516                        if ( !pDev->running ){
1517                                return RTEMS_INVALID_NAME;
1518                        }
1519                        /* Disable interrupts */
1520                        drvmgr_interrupt_unregister(dev, 0, grspw_interrupt, pDev);
1521
1522                        pDev->running = 0;
1523
1524                        /* Stop Receiver and transmitter */
1525                        grspw_hw_stop(pDev,1,1);
1526                        break;
1527
1528                /* Set time-code control register bits, and Enables/Disables
1529                 * Time code interrupt, make sure to connect the callback
1530                 * grspw_timecode_callback if using interrupts.
1531                 */
1532                case SPACEWIRE_IOCTRL_SET_TCODE_CTRL:
1533                        tmp = (unsigned int)ioarg->buffer;
1534                        mask = tmp & (SPACEWIRE_TCODE_CTRL_IE_MSK|SPACEWIRE_TCODE_CTRL_TT_MSK|SPACEWIRE_TCODE_CTRL_TR_MSK);
1535                        mask <<= 8;
1536                        tmp &= mask;
1537                        tmp = (SPW_CTRL_READ(pDev) & ~(mask | SPW_CTRL_IE)) | tmp;
1538                        if (tmp & (SPW_CTRL_LI|SPW_CTRL_TQ))
1539                                tmp |= SPW_CTRL_IE;
1540                        SPW_CTRL_WRITE(pDev, tmp);
1541                        break;
1542
1543                /* Set time register and optionaly send a time code */
1544                case SPACEWIRE_IOCTRL_SET_TCODE:
1545                        tmp = (unsigned int)ioarg->buffer;
1546                        /* Set timecode register */
1547                        if (tmp & SPACEWIRE_TCODE_SET) {
1548                                SPW_WRITE(&pDev->regs->time,
1549                                    ((SPW_READ(&pDev->regs->time) & ~(0xff)) |
1550                                    (tmp & SPACEWIRE_TCODE_TCODE)));
1551                        }
1552                        /* Send timecode directly (tick-in) ? */
1553                        if (tmp & SPACEWIRE_TCODE_TX) {
1554                            SPW_CTRL_WRITE(pDev,
1555                                ((SPW_CTRL_READ(pDev) & ~(SPW_CTRL_TI)) | SPW_CTRL_TI));
1556                        }
1557                        break;
1558
1559                /* Read time code register and tick-out status bit */
1560                case SPACEWIRE_IOCTRL_GET_TCODE:
1561                        tmp = (unsigned int)ioarg->buffer;
1562                        if ( !tmp ){
1563                            return RTEMS_INVALID_NAME;
1564                        }
1565
1566                        /* Copy timecode register */
1567                        if (SPW_READ(&pDev->regs->status) & SPW_STATUS_TO) {
1568                                *(unsigned int *)tmp = (1 << 8) | SPW_READ(&pDev->regs->time);
1569                        } else {
1570                                *(unsigned int *)tmp = SPW_READ(&pDev->regs->time);
1571                        }
1572                        break;
1573
1574                case SPACEWIRE_IOCTRL_SET_READ_TIMEOUT:
1575                        pDev->config.rtimeout = (unsigned int)ioarg->buffer;
1576                        break;
1577
1578                default:
1579                        return RTEMS_NOT_IMPLEMENTED;
1580        }
1581
1582        SPACEWIRE_DBGC(DBGSPW_IOCALLS, "SPW_IOCTRL Return\n");
1583        return RTEMS_SUCCESSFUL;
1584}
1585
1586/* ============================================================================== */
1587
1588static int grspw_set_rxmaxlen(GRSPW_DEV *pDev) {
1589        unsigned int rxmax;
1590        SPW_WRITE(&pDev->regs->dma0rxmax,pDev->config.rxmaxlen); /*set rx maxlength*/
1591        rxmax = SPW_READ(&pDev->regs->dma0rxmax);
1592        if (rxmax != pDev->config.rxmaxlen) {
1593                return 0;
1594        }
1595        return 1;
1596}
1597
1598static int grspw_hw_init(GRSPW_DEV *pDev) {
1599        unsigned int ctrl;
1600
1601        ctrl = SPW_CTRL_READ(pDev);
1602
1603        pDev->rx = (SPACEWIRE_RXBD *) pDev->ptr_bd0;
1604        pDev->tx = (SPACEWIRE_TXBD *) (pDev->ptr_bd0 + SPACEWIRE_BDTABLE_SIZE);
1605
1606        /* Set up remote addresses */
1607        pDev->rx_remote = (unsigned int)pDev->ptr_bd0_remote;
1608        pDev->tx_remote = pDev->rx_remote + SPACEWIRE_BDTABLE_SIZE;
1609
1610        SPACEWIRE_DBG("hw_init [minor %i]\n", pDev->minor);
1611
1612        pDev->config.is_rmap = ctrl & SPW_CTRL_RA;
1613        pDev->config.is_rxunaligned = ctrl & SPW_CTRL_RX;
1614        pDev->config.is_rmapcrc = ctrl & SPW_CTRL_RC;
1615        return 0;
1616}
1617
1618static int grspw_hw_waitlink (GRSPW_DEV *pDev, int timeout)
1619{
1620        int j;
1621
1622        /* No actual link interface on a DMA-only GRSPW2 connected to the
1623         * SPW router
1624         */
1625        if (pDev->core_ver == 3)
1626                return 0;
1627
1628        if ( timeout == -1 ){
1629                /* Wait default timeout */
1630                timeout = SPACEWIRE_INIT_TIMEOUT;
1631        }
1632
1633        j=0;
1634        while (SPW_LINKSTATE(SPW_STATUS_READ(pDev)) != 5) {
1635                if ( timeout < -1 ) {
1636                        /* wait forever */
1637                }else if ( j >= timeout ){
1638                        /* timeout reached, return fail */
1639                        return 1;
1640                }
1641
1642                /* Sleep for 10 ticks */
1643                rtems_task_wake_after(10);
1644                j+=10;
1645        }
1646        return 0;
1647}
1648
1649static void grspw_hw_reset(GRSPW_DEV *pDev)
1650{
1651        SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET); /*reset core*/
1652        SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE |
1653                         SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/
1654
1655        /* Add extra writes to make sure we wait the number of clocks required
1656         * after reset
1657         */
1658        SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE |
1659                SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/
1660        SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE |
1661                SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/
1662        SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE |
1663                SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/
1664        SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE |
1665                SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/
1666
1667        SPW_CTRL_WRITE(pDev, SPW_CTRL_LINKSTART); /*start link core*/
1668}
1669
1670static void grspw_hw_read_config(GRSPW_DEV *pDev)
1671{
1672        unsigned int tmp;
1673
1674        tmp = SPW_READ(&pDev->regs->nodeaddr);
1675        pDev->config.nodeaddr = 0xFF & tmp;
1676        pDev->config.nodemask = 0xFF & (tmp>>8);
1677        pDev->config.destkey = 0xFF & SPW_READ(&pDev->regs->destkey);
1678        pDev->config.clkdiv = 0xFFFF & SPW_READ(&pDev->regs->clkdiv);
1679
1680        tmp = SPW_CTRL_READ(pDev);
1681        pDev->config.promiscuous = 1 & (tmp >> 5);
1682        pDev->config.rmapen = 1 & (tmp >> 16);
1683        pDev->config.rmapbufdis = 1 & (tmp >> 17);
1684        pDev->config.is_rmap = 1 & (tmp >> 31);
1685        pDev->config.is_rxunaligned = 1 & (tmp >> 30);
1686        pDev->config.is_rmapcrc = 1 & (tmp >> 29);
1687        pDev->config.linkdisabled = 1 & tmp;
1688        pDev->config.linkstart = 1 & (tmp >> 1);
1689
1690        if ( pDev->core_ver <= 1 ){
1691                tmp = SPW_READ(&pDev->regs->timer);
1692                pDev->config.timer = 0xFFF & tmp;
1693                pDev->config.disconnect = 0x3FF & (tmp >> 12);
1694        }else{
1695                pDev->config.timer = 0;
1696                pDev->config.disconnect = 0;
1697        }
1698
1699        return;
1700}
1701
1702/* timeout is given in ticks */
1703static int grspw_hw_startup (GRSPW_DEV *pDev, int timeout)
1704{
1705        int i;
1706        unsigned int dmactrl;
1707
1708        SPW_WRITE(&pDev->regs->status, (SPW_STATUS_TO|SPW_STATUS_CE|SPW_STATUS_ER|SPW_STATUS_DE|SPW_STATUS_PE|SPW_STATUS_WE|SPW_STATUS_IA|SPW_STATUS_EE)); /*clear status*/
1709
1710        if (grspw_hw_waitlink(pDev,timeout)) {
1711                SPACEWIRE_DBG2("Device open. Link is not up\n");
1712                return RTEMS_TIMEOUT;
1713        }
1714
1715        SPW_WRITE(&pDev->regs->dma0ctrl, SPW_DMACTRL_PS | SPW_DMACTRL_PR | SPW_DMACTRL_TA | SPW_DMACTRL_RA); /*clear status, set ctrl*/
1716
1717        if ((dmactrl = SPW_READ(&pDev->regs->dma0ctrl)) != 0) {
1718                SPACEWIRE_DBG2("DMACtrl is not cleared\n");
1719                return RTEMS_IO_ERROR;
1720        }
1721
1722        /* prepare transmit buffers */
1723        for (i = 0; i < pDev->txbufcnt; i++) {
1724                pDev->tx[i].ctrl = 0;
1725                pDev->tx[i].addr_header = ((unsigned int)&pDev->ptr_txhbuf0_remote[0]) + (i * pDev->txhbufsize);
1726                pDev->tx[i].addr_data = ((unsigned int)&pDev->ptr_txdbuf0_remote[0]) + (i * pDev->txdbufsize);
1727        }
1728        pDev->tx_cur = 0;
1729        pDev->tx_sent = 0;
1730        pDev->tx_all_in_use = 0;
1731
1732        /* prepare receive buffers */
1733        for (i = 0; i < pDev->rxbufcnt; i++) {
1734                if (i+1 == pDev->rxbufcnt) {
1735                        pDev->rx[i].ctrl = SPW_RXBD_IE | SPW_RXBD_EN | SPW_RXBD_WR;
1736                } else {
1737                        pDev->rx[i].ctrl = SPW_RXBD_IE | SPW_RXBD_EN;
1738                }
1739                pDev->rx[i].addr = ((unsigned int)&pDev->ptr_rxbuf0_remote[0]) + (i * pDev->rxbufsize);
1740        }
1741        pDev->rxcur = 0;
1742        pDev->rxbufcur = -1;
1743        grspw_set_rxmaxlen(pDev);
1744
1745        SPW_WRITE(&pDev->regs->dma0txdesc, pDev->tx_remote);
1746        SPW_WRITE(&pDev->regs->dma0rxdesc, pDev->rx_remote);
1747
1748        /* start RX */
1749        dmactrl = SPW_READ(&pDev->regs->dma0ctrl);
1750        SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) | SPW_DMACTRL_RD | SPW_DMACTRL_RXEN | SPW_DMACTRL_NS | SPW_DMACTRL_TXIE | SPW_DMACTRL_RXIE);
1751
1752        SPACEWIRE_DBGC(DBGSPW_TX,"0x%x: setup complete\n", (unsigned int)pDev->regs);
1753        return RTEMS_SUCCESSFUL;
1754}
1755
1756/* Wait until the receiver is inactive */
1757static void grspw_hw_wait_rx_inactive(GRSPW_DEV *pDev)
1758{
1759        while( SPW_READ(&pDev->regs->dma0ctrl) & SPW_DMACTRL_RX ){
1760                /* switching may be needed:
1761                 *  - low frequency GRSPW
1762                 *  - mega packet incoming
1763                 */
1764                rtems_task_wake_after(1);
1765        }
1766}
1767
1768/* Stop the rx or/and tx by disabling the receiver/transmitter */
1769static int grspw_hw_stop (GRSPW_DEV *pDev, int rx, int tx)
1770{
1771        unsigned int dmactrl;
1772
1773        /* stop rx and/or tx */
1774        dmactrl = SPW_READ(&pDev->regs->dma0ctrl);
1775        if ( rx ) {
1776                dmactrl &= ~(SPW_DMACTRL_RXEN|SPW_DMACTRL_RXIE|SPW_DMACTRL_RD);
1777        }
1778        if ( tx ) {
1779                dmactrl &= ~(SPW_DMACTRL_TXEN|SPW_DMACTRL_TXIE);
1780        }
1781        /*SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) & ~(SPW_DMACTRL_RD | SPW_DMACTRL_RXEN) & ~(SPW_DMACTRL_TXEN));*/
1782
1783        /* don't clear status flags */
1784        dmactrl &= ~(SPW_DMACTRL_RA|SPW_DMACTRL_PR|SPW_DMACTRL_AI);
1785        SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl);
1786        return RTEMS_SUCCESSFUL;
1787}
1788
1789
1790
1791int grspw_hw_send(GRSPW_DEV *pDev, unsigned int hlen, char *hdr, unsigned int dlen, char *data, unsigned int options)
1792{
1793        unsigned int dmactrl, ctrl;
1794#ifdef DEBUG_SPACEWIRE_ONOFF
1795        unsigned int k;
1796#endif
1797        rtems_interrupt_level level;
1798        unsigned int cur = pDev->tx_cur, bdctrl;
1799        char *txh = pDev->ptr_txhbuf0 + (cur * pDev->txhbufsize);
1800        char *txd = pDev->ptr_txdbuf0 + (cur * pDev->txdbufsize);
1801        char *txh_remote = pDev->ptr_txhbuf0_remote + (cur * pDev->txhbufsize);
1802        char *txd_remote = pDev->ptr_txdbuf0_remote + (cur * pDev->txdbufsize);
1803       
1804        ctrl = SPW_READ((volatile void *)&pDev->tx[cur].ctrl);
1805
1806        if (ctrl & SPW_TXBD_EN) {
1807                return 0;
1808        }
1809
1810        memcpy(&txd[0], data, dlen);
1811        memcpy(&txh[0], hdr, hlen);
1812
1813#ifdef DEBUG_SPACEWIRE_ONOFF 
1814        if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) {
1815                for (k = 0; k < hlen; k++){
1816                        if (k % 16 == 0) {
1817                                printf ("\n");
1818                        }
1819                        printf ("%.2x(%c) ",txh[k] & 0xff,isprint(txh[k] & 0xff) ? txh[k] & 0xff : ' ');
1820                }
1821                printf ("\n");
1822        }
1823        if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) {
1824                for (k = 0; k < dlen; k++){
1825                        if (k % 16 == 0) {
1826                                printf ("\n");
1827                        }
1828                        printf ("%.2x(%c) ",txd[k] & 0xff,isprint(txd[k] & 0xff) ? txd[k] & 0xff : ' ');
1829                }
1830                printf ("\n");
1831        }
1832#endif
1833       
1834        pDev->tx[cur].addr_header = (unsigned int)txh_remote;
1835        pDev->tx[cur].len = dlen;
1836        pDev->tx[cur].addr_data = (unsigned int)txd_remote;
1837
1838        bdctrl = SPW_TXBD_IE | SPW_TXBD_EN | hlen;
1839        if ( options & GRSPW_PKTSEND_OPTION_HDR_CRC )
1840                bdctrl |= SPW_TXBD_HC;
1841        if ( options & GRSPW_PKTSEND_OPTION_DATA_CRC )
1842                bdctrl |= SPW_TXBD_DC;
1843        bdctrl |= options & GRSPW_PKTSEND_OPTION_NOCRCLEN_MASK;
1844
1845        /* Update counters */
1846        rtems_interrupt_disable(level);
1847        if (pDev->tx_cur == (pDev->txbufcnt - 1) ) {
1848                bdctrl |= SPW_TXBD_WR;
1849        }
1850        pDev->tx[cur].ctrl = bdctrl;
1851
1852        dmactrl = SPW_READ(&pDev->regs->dma0ctrl);
1853        SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_TX) | SPW_DMACTRL_TXEN | SPW_DMACTRL_TXIE);
1854
1855        pDev->tx_cur = (pDev->tx_cur + 1) % pDev->txbufcnt;
1856        if (pDev->tx_cur == pDev->tx_sent) {
1857                pDev->tx_all_in_use = 1;
1858        }
1859        rtems_interrupt_enable(level);
1860
1861        /* In blocking mode wait until message is sent */
1862        if (pDev->config.tx_blocking) {
1863                while ( SPW_READ(&pDev->regs->dma0ctrl) & SPW_DMACTRL_TXEN) {
1864                        /* if changed to blocking mode  */
1865                        SPACEWIRE_DBGC(DBGSPW_TX, "Tx blocking\n");
1866                        rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1867                }
1868        }
1869        SPACEWIRE_DBGC(DBGSPW_TX, "0x%x: transmitted <%i> bytes\n", (unsigned int) pDev->regs, dlen+hlen);
1870        return hlen + dlen;
1871}
1872
1873static int grspw_hw_receive(GRSPW_DEV *pDev, char *b, int c) {
1874        unsigned int len, rxlen, ctrl;
1875        unsigned int cur;
1876        unsigned int tmp;
1877        unsigned int dump_start_len;
1878        int i;
1879        char *rxb; 
1880
1881        if ( pDev->config.promiscuous || pDev->config.keep_source ) {
1882                dump_start_len = 0; /* make sure address and prot can be read in promiscuous mode */
1883        } else if (pDev->config.rm_prot_id) {
1884                dump_start_len = 2; /* skip source address and protocol id */
1885        } else {
1886                dump_start_len = 1; /* default: skip only source address */
1887        }
1888
1889        rxlen = 0;
1890        cur = pDev->rxcur;
1891        rxb = pDev->ptr_rxbuf0 + (cur * pDev->rxbufsize);
1892
1893        SPACEWIRE_DBGC(DBGSPW_RX, "0x%x: waitin packet at pos %i\n", (unsigned int) pDev->regs, cur);
1894
1895        ctrl = SPW_READ((volatile void *)&pDev->rx[cur].ctrl);
1896        if (ctrl & SPW_RXBD_EN) {
1897                return rxlen;
1898        }
1899        SPACEWIRE_DBGC(DBGSPW_RX, "checking packet\n");
1900
1901        len = SPW_RXBD_LENGTH & ctrl;
1902        if (!((ctrl & SPW_RXBD_ERROR) || (pDev->config.check_rmap_err && (ctrl & SPW_RXBD_RMAPERROR)))) {
1903                if (pDev->rxbufcur == -1) {
1904                        SPACEWIRE_DBGC(DBGSPW_RX, "incoming packet len %i\n", len);
1905                        pDev->stat.packets_received++;
1906                        pDev->rxbufcur = dump_start_len;
1907                }
1908                rxlen = tmp = len - pDev->rxbufcur;
1909                SPACEWIRE_DBGC(DBGSPW_RX, "C %i\n", c);
1910                SPACEWIRE_DBGC(DBGSPW_RX, "Dump %i\n", dump_start_len);
1911                SPACEWIRE_DBGC(DBGSPW_RX, "Bufcur %i\n", pDev->rxbufcur);
1912                SPACEWIRE_DBGC(DBGSPW_RX, "Rxlen %i\n", rxlen );
1913                if (rxlen > c) {
1914                        rxlen = c;
1915                }
1916                if (CPU_SPARC_HAS_SNOOPING) {
1917/*              if ( 1 ) {*/
1918                        /*printf("RX_MEMCPY(0x%x, 0x%x, 0x%x)\n", (unsigned int)b, (unsigned int)(rxb+pDev->rxbufcur), (unsigned int)rxlen);*/
1919                        memcpy(b, rxb+pDev->rxbufcur, rxlen);
1920                } else {
1921                        int left = rxlen;
1922                        /* Copy word wise if Aligned */
1923                        if ( (((int)b & 3) == 0) && (((int)(rxb+pDev->rxbufcur) & 3) == 0) ){
1924                                while(left>=32){
1925                                        *(int *)(b+0) = MEM_READ32(rxb+pDev->rxbufcur+0);
1926                                        *(int *)(b+4) = MEM_READ32(rxb+pDev->rxbufcur+4);
1927                                        *(int *)(b+8) = MEM_READ32(rxb+pDev->rxbufcur+8);
1928                                        *(int *)(b+12) = MEM_READ32(rxb+pDev->rxbufcur+12);
1929                                        *(int *)(b+16) = MEM_READ32(rxb+pDev->rxbufcur+16);
1930                                        *(int *)(b+20) = MEM_READ32(rxb+pDev->rxbufcur+20);
1931                                        *(int *)(b+24) = MEM_READ32(rxb+pDev->rxbufcur+24);
1932                                        *(int *)(b+28) = MEM_READ32(rxb+pDev->rxbufcur+28);
1933                                        rxb+=32;
1934                                        b+=32;
1935                                        left-=32;
1936                                }
1937                                while(left>=4){
1938                                        *(int *)b = MEM_READ32(rxb+pDev->rxbufcur);
1939                                        rxb+=4;
1940                                        b+=4;
1941                                        left-=4;
1942                                }
1943                        }
1944                        for(i = 0; i < left; i++) {
1945                                b[i] = MEM_READ8(rxb+pDev->rxbufcur+i);
1946                        }
1947                }
1948
1949                pDev->rxbufcur += rxlen;
1950                if (c >= tmp) {
1951                        SPACEWIRE_DBGC(DBGSPW_RX, "Next descriptor\n");
1952                        grspw_rxnext(pDev);
1953                }
1954        } else {
1955                check_rx_errors(pDev, ctrl);
1956                grspw_rxnext(pDev);
1957        }
1958        return rxlen;
1959}
1960
1961static void grspw_rxnext(GRSPW_DEV *pDev)
1962{
1963        unsigned int dmactrl;
1964        unsigned int cur = pDev->rxcur;
1965        unsigned int ctrl = 0;
1966        rtems_interrupt_level level;
1967
1968        rtems_interrupt_disable(level);
1969
1970        if (cur == (pDev->rxbufcnt - 1)) {
1971                pDev->rx[cur].ctrl = ctrl | SPW_RXBD_EN | SPW_RXBD_IE | SPW_RXBD_WR;
1972                cur = 0;
1973        } else {
1974                pDev->rx[cur].ctrl = ctrl | SPW_RXBD_EN | SPW_RXBD_IE;
1975                cur++;
1976        }
1977
1978        pDev->rxcur = cur;
1979        pDev->rxbufcur = -1;
1980
1981        /* start RX */
1982        dmactrl = SPW_READ(&pDev->regs->dma0ctrl);
1983        SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) | SPW_DMACTRL_RD | SPW_DMACTRL_RXEN | SPW_DMACTRL_RXIE | SPW_DMACTRL_NS);
1984
1985        rtems_interrupt_enable(level);
1986}
1987
1988static void check_rx_errors(GRSPW_DEV *pDev, int ctrl)
1989{
1990        if (ctrl & SPW_RXBD_EEP) {
1991                pDev->stat.rx_eep_err++;
1992        }
1993        if (ctrl & SPW_RXBD_EHC) {
1994                if (pDev->config.check_rmap_err) {
1995                        pDev->stat.rx_rmap_header_crc_err++;
1996                }
1997        } 
1998        if (ctrl & SPW_RXBD_EDC) {
1999                if (pDev->config.check_rmap_err) {
2000                        pDev->stat.rx_rmap_data_crc_err++;
2001                }
2002        }
2003        if (ctrl & SPW_RXBD_ETR) {
2004                pDev->stat.rx_truncated++;
2005        }
2006}
2007
2008
2009static void grspw_print_dev(struct drvmgr_dev *dev, int options)
2010{
2011        GRSPW_DEV *pDev = dev->priv;
2012
2013        /* Print */
2014        printf("--- GRSPW %s ---\n", pDev->devName);
2015        printf(" REGS:            0x%x\n", (unsigned int)pDev->regs);
2016        printf(" IRQ:             %d\n", pDev->irq);
2017        printf(" CORE VERSION:    %d\n", pDev->core_ver);
2018        printf(" CTRL:            0x%x\n", pDev->regs->ctrl);
2019        printf(" STATUS:          0x%x\n", pDev->regs->status);
2020        printf(" DMA0CTRL:        0x%x\n", pDev->regs->dma0ctrl);
2021        printf(" TXBD:            0x%x\n", (unsigned int)pDev->tx);
2022        printf(" RXBD:            0x%x\n", (unsigned int)pDev->rx);
2023}
2024
2025void grspw_print(int options)
2026{
2027        struct amba_drv_info *drv = &grspw_drv_info;
2028        struct drvmgr_dev *dev;
2029
2030        dev = drv->general.dev;
2031        while(dev) {
2032                grspw_print_dev(dev, options);
2033                dev = dev->next_in_drv;
2034        }
2035}
Note: See TracBrowser for help on using the repository browser.