Kernel  |  3.14

下载     查看原文件
C++程序  |  350行  |  8.19 KB
/* Copyright (C) 2003-2005  SBE, Inc.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/slab.h>
#include <linux/io.h>
#include <asm/byteorder.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/hdlc.h>
#include "pmcc4_sysdep.h"
#include "sbecom_inline_linux.h"
#include "libsbew.h"
#include "pmcc4.h"

#if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
#define _v7_hdlc_  1
#else
#define _v7_hdlc_  0
#endif

#if _v7_hdlc_
#define V7(x) (x ## _v7)
extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
extern int  register_hdlc_device_v7 (hdlc_device *);
extern int  unregister_hdlc_device_v7 (hdlc_device *);

#else
#define V7(x) x
#endif


#ifndef USE_MAX_INT_DELAY
static int  dummy = 0;

#endif

extern int  cxt1e1_log_level;
extern int  drvr_state;


#if 1
u_int32_t
pci_read_32 (u_int32_t *p)
{
#ifdef FLOW_DEBUG
    u_int32_t   v;

    FLUSH_PCI_READ ();
    v = le32_to_cpu (*p);
    if (cxt1e1_log_level >= LOG_DEBUG)
        pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
    return v;
#else
    FLUSH_PCI_READ ();              /* */
    return le32_to_cpu (*p);
#endif
}

void
pci_write_32 (u_int32_t *p, u_int32_t v)
{
#ifdef FLOW_DEBUG
    if (cxt1e1_log_level >= LOG_DEBUG)
        pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
#endif
    *p = cpu_to_le32 (v);
    FLUSH_PCI_WRITE ();             /* This routine is called from routines
                                     * which do multiple register writes
                                     * which themselves need flushing between
                                     * writes in order to guarantee write
                                     * ordering.  It is less code-cumbersome
                                     * to flush here-in then to investigate
                                     * and code the many other register
                                     * writing routines. */
}
#endif


void
pci_flush_write (ci_t *ci)
{
    volatile u_int32_t v;

    /* issue a PCI read to flush PCI write thru bridge */
    v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */

    /*
     * return nothing, this just reads PCI bridge interface to flush
     * previously written data
     */
}


static void
watchdog_func (unsigned long arg)
{
    struct watchdog *wd = (void *) arg;

    if (drvr_state != SBE_DRVR_AVAILABLE)
    {
        if (cxt1e1_log_level >= LOG_MONITOR)
            pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state);
        return;
    }
    schedule_work (&wd->work);
    mod_timer (&wd->h, jiffies + wd->ticks);
}

int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec)
{
    wdp->func = f;
    wdp->softc = c;
    wdp->ticks = (HZ) * (usec / 1000) / 1000;
    INIT_WORK(&wdp->work, (void *)f);
    init_timer (&wdp->h);
    {
        ci_t       *ci = (ci_t *) c;

        wdp->h.data = (unsigned long) &ci->wd;
    }
    wdp->h.function = watchdog_func;
    return 0;
}

void
OS_uwait (int usec, char *description)
{
    int         tmp;

    if (usec >= 1000)
    {
        mdelay (usec / 1000);
        /* now delay residual */
        tmp = (usec / 1000) * 1000; /* round */
        tmp = usec - tmp;           /* residual */
        if (tmp)
        {                           /* wait on residual */
            udelay (tmp);
        }
    } else
    {
        udelay (usec);
    }
}

/* dummy short delay routine called as a subroutine so that compiler
 * does not optimize/remove its intent (a short delay)
 */

void
OS_uwait_dummy (void)
{
#ifndef USE_MAX_INT_DELAY
    dummy++;
#else
    udelay (1);
#endif
}


void
OS_sem_init (void *sem, int state)
{
    switch (state)
    {
        case SEM_TAKEN:
		sema_init((struct semaphore *) sem, 0);
        break;
    case SEM_AVAILABLE:
	    sema_init((struct semaphore *) sem, 1);
        break;
    default:                        /* otherwise, set sem.count to state's
                                     * value */
        sema_init (sem, state);
        break;
    }
}


int
sd_line_is_ok (void *user)
{
    struct net_device *ndev = (struct net_device *) user;

    return netif_carrier_ok (ndev);
}

void
sd_line_is_up (void *user)
{
    struct net_device *ndev = (struct net_device *) user;

    netif_carrier_on (ndev);
    return;
}

void
sd_line_is_down (void *user)
{
    struct net_device *ndev = (struct net_device *) user;

    netif_carrier_off (ndev);
    return;
}

void
sd_disable_xmit (void *user)
{
    struct net_device *dev = (struct net_device *) user;

    netif_stop_queue (dev);
    return;
}

void
sd_enable_xmit (void *user)
{
    struct net_device *dev = (struct net_device *) user;

    netif_wake_queue (dev);
    return;
}

int
sd_queue_stopped (void *user)
{
    struct net_device *ndev = (struct net_device *) user;

    return netif_queue_stopped (ndev);
}

void sd_recv_consume(void *token, size_t len, void *user)
{
    struct net_device *ndev = user;
    struct sk_buff *skb = token;

    skb->dev = ndev;
    skb_put (skb, len);
    skb->protocol = hdlc_type_trans(skb, ndev);
    netif_rx(skb);
}


/**
 ** Read some reserved location w/in the COMET chip as a usable
 ** VMETRO trigger point or other trace marking event.
 **/

#include "comet.h"

extern ci_t *CI;                /* dummy pointer to board ZERO's data */
void
VMETRO_TRACE (void *x)
{
    u_int32_t   y = (u_int32_t) x;

    pci_write_32 ((u_int32_t *) &CI->cpldbase->leds, y);
}


void
VMETRO_TRIGGER (ci_t *ci, int x)
{
    struct s_comet_reg    *comet;
    volatile u_int32_t data;

    comet = ci->port[0].cometbase;  /* default to COMET # 0 */

    switch (x)
    {
    default:
    case 0:
        data = pci_read_32 ((u_int32_t *) &comet->__res24);     /* 0x90 */
        break;
    case 1:
        data = pci_read_32 ((u_int32_t *) &comet->__res25);     /* 0x94 */
        break;
    case 2:
        data = pci_read_32 ((u_int32_t *) &comet->__res26);     /* 0x98 */
        break;
    case 3:
        data = pci_read_32 ((u_int32_t *) &comet->__res27);     /* 0x9C */
        break;
    case 4:
        data = pci_read_32 ((u_int32_t *) &comet->__res88);     /* 0x220 */
        break;
    case 5:
        data = pci_read_32 ((u_int32_t *) &comet->__res89);     /* 0x224 */
        break;
    case 6:
        data = pci_read_32 ((u_int32_t *) &comet->__res8A);     /* 0x228 */
        break;
    case 7:
        data = pci_read_32 ((u_int32_t *) &comet->__res8B);     /* 0x22C */
        break;
    case 8:
        data = pci_read_32 ((u_int32_t *) &comet->__resA0);     /* 0x280 */
        break;
    case 9:
        data = pci_read_32 ((u_int32_t *) &comet->__resA1);     /* 0x284 */
        break;
    case 10:
        data = pci_read_32 ((u_int32_t *) &comet->__resA2);     /* 0x288 */
        break;
    case 11:
        data = pci_read_32 ((u_int32_t *) &comet->__resA3);     /* 0x28C */
        break;
    case 12:
        data = pci_read_32 ((u_int32_t *) &comet->__resA4);     /* 0x290 */
        break;
    case 13:
        data = pci_read_32 ((u_int32_t *) &comet->__resA5);     /* 0x294 */
        break;
    case 14:
        data = pci_read_32 ((u_int32_t *) &comet->__resA6);     /* 0x298 */
        break;
    case 15:
        data = pci_read_32 ((u_int32_t *) &comet->__resA7);     /* 0x29C */
        break;
    case 16:
        data = pci_read_32 ((u_int32_t *) &comet->__res74);     /* 0x1D0 */
        break;
    case 17:
        data = pci_read_32 ((u_int32_t *) &comet->__res75);     /* 0x1D4 */
        break;
    case 18:
        data = pci_read_32 ((u_int32_t *) &comet->__res76);     /* 0x1D8 */
        break;
    case 19:
        data = pci_read_32 ((u_int32_t *) &comet->__res77);     /* 0x1DC */
        break;
    }
}


/***  End-of-File  ***/