source: rtems/bsps/shared/grlib/spw/grspw.c @ c1dcd6af

5
Last change on this file since c1dcd6af was c1dcd6af, checked in by Jiri Gaisler <jiri@…>, on 01/21/19 at 10:27:07

grlib: make memory coherency cpu-independent

Update #3678.

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