示例#1
0
void
cleanup_devs (void)
{
    hdw_info_t *hi;
    int         i;

    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
    {
        if (hi->pci_slot == 0xff || !hi->ndev)
            break;
        c4_stopwd(netdev_priv(hi->ndev));
#ifdef CONFIG_PROC_FS
        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
#endif
        unregister_netdev (hi->ndev);
        free_irq (hi->pdev[0]->irq, hi->ndev);
#ifdef CONFIG_SBE_PMCC4_NCOMM
        free_irq (hi->pdev[1]->irq, hi->ndev);
#endif
        OS_kfree (hi->ndev);
    }
}
示例#2
0
struct net_device *__init
c4_add_dev (hdw_info_t * hi, int brdno, unsigned long f0, unsigned long f1,
            int irq0, int irq1)
{
    struct net_device *ndev;
    ci_t       *ci;

    ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
    if (!ndev)
    {
        pr_warning("%s: no memory for struct net_device !\n", hi->devname);
        error_flag = ENOMEM;
        return 0;
    }
    ci = (ci_t *)(netdev_priv(ndev));
    ndev->irq = irq0;

    ci->hdw_info = hi;
    ci->state = C_INIT;         /* mark as hardware not available */
    ci->next = c4_list;
    c4_list = ci;
    ci->brdno = ci->next ? ci->next->brdno + 1 : 0;

    if (CI == 0)
        CI = ci;                    /* DEBUG, only board 0 usage */

    strcpy (ci->devname, hi->devname);
    ci->release = &pmcc4_OSSI_release[0];

    /* tasklet */
#if defined(SBE_ISR_TASKLET)
    tasklet_init (&ci->ci_musycc_isr_tasklet,
                  (void (*) (unsigned long)) musycc_intr_bh_tasklet,
                  (unsigned long) ci);

    if (atomic_read (&ci->ci_musycc_isr_tasklet.count) == 0)
        tasklet_disable_nosync (&ci->ci_musycc_isr_tasklet);
#elif defined(SBE_ISR_IMMEDIATE)
    ci->ci_musycc_isr_tq.routine = (void *) (unsigned long) musycc_intr_bh_tasklet;
    ci->ci_musycc_isr_tq.data = ci;
#endif


    if (register_netdev (ndev) ||
        (c4_init (ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
    {
        OS_kfree (netdev_priv(ndev));
        OS_kfree (ndev);
        error_flag = ENODEV;
        return 0;
    }
    /*************************************************************
     *  int request_irq(unsigned int irq,
     *                  void (*handler)(int, void *, struct pt_regs *),
     *                  unsigned long flags, const char *dev_name, void *dev_id);
     *  wherein:
     *  irq      -> The interrupt number that is being requested.
     *  handler  -> Pointer to handling function being installed.
     *  flags    -> A bit mask of options related to interrupt management.
     *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
     *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
     *              private data area (to identify which device is interrupting).
     *
     *  extern void free_irq(unsigned int irq, void *dev_id);
     **************************************************************/

    if (request_irq (irq0, &c4_linux_interrupt,
                     IRQF_SHARED,
                     ndev->name, ndev))
    {
        pr_warning("%s: MUSYCC could not get irq: %d\n", ndev->name, irq0);
        unregister_netdev (ndev);
        OS_kfree (netdev_priv(ndev));
        OS_kfree (ndev);
        error_flag = EIO;
        return 0;
    }
#ifdef CONFIG_SBE_PMCC4_NCOMM
    if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
    {
        pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
        unregister_netdev (ndev);
        free_irq (irq0, ndev);
        OS_kfree (netdev_priv(ndev));
        OS_kfree (ndev);
        error_flag = EIO;
        return 0;
    }
#endif

    /* setup board identification information */

    {
        u_int32_t   tmp;

        hdw_sn_get (hi, brdno);     /* also sets PROM format type (promfmt)
                                     * for later usage */

        switch (hi->promfmt)
        {
        case PROM_FORMAT_TYPE1:
            memcpy (ndev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
            memcpy (&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);     /* unaligned data
                                                                         * acquisition */
            ci->brd_id = cpu_to_be32 (tmp);
            break;
        case PROM_FORMAT_TYPE2:
            memcpy (ndev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
            memcpy (&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);     /* unaligned data
                                                                         * acquisition */
            ci->brd_id = cpu_to_be32 (tmp);
            break;
        default:
            ci->brd_id = 0;
            memset (ndev->dev_addr, 0, 6);
            break;
        }

#if 1
        sbeid_set_hdwbid (ci);      /* requires bid to be preset */
#else
        sbeid_set_bdtype (ci);      /* requires hdw_bid to be preset */
#endif

    }

#ifdef CONFIG_PROC_FS
    sbecom_proc_brd_init (ci);
#endif
#if defined(SBE_ISR_TASKLET)
    tasklet_enable (&ci->ci_musycc_isr_tasklet);
#endif


    if ((error_flag = c4_init2 (ci)) != SBE_DRVR_SUCCESS)
    {
#ifdef CONFIG_PROC_FS
        sbecom_proc_brd_cleanup (ci);
#endif
        unregister_netdev (ndev);
        free_irq (irq1, ndev);
        free_irq (irq0, ndev);
        OS_kfree (netdev_priv(ndev));
        OS_kfree (ndev);
        return 0;                   /* failure, error_flag is set */
    }
    return ndev;
}
示例#3
0
STATIC struct net_device *
create_chan (struct net_device * ndev, ci_t * ci,
             struct sbecom_chan_param * cp)
{
    hdlc_device *hdlc;
    struct net_device *dev;
    hdw_info_t *hi;
    int         ret;

    if (c4_find_chan (cp->channum))
        return 0;                   /* channel already exists */

    {
        struct c4_priv *priv;

        /* allocate then fill in private data structure */
        priv = OS_kmalloc (sizeof (struct c4_priv));
        if (!priv)
        {
            pr_warning("%s: no memory for net_device !\n", ci->devname);
            return 0;
        }
        dev = alloc_hdlcdev (priv);
        if (!dev)
        {
            pr_warning("%s: no memory for hdlc_device !\n", ci->devname);
            OS_kfree (priv);
            return 0;
        }
        priv->ci = ci;
        priv->channum = cp->channum;
    }

    hdlc = dev_to_hdlc (dev);

    dev->base_addr = 0;             /* not I/O mapped */
    dev->irq = ndev->irq;
    dev->type = ARPHRD_RAWHDLC;
    *dev->name = 0;                 /* default ifconfig name = "hdlc" */

    hi = (hdw_info_t *) ci->hdw_info;
    if (hi->mfg_info_sts == EEPROM_OK)
    {
        switch (hi->promfmt)
        {
        case PROM_FORMAT_TYPE1:
            memcpy (dev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
            break;
        case PROM_FORMAT_TYPE2:
            memcpy (dev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
            break;
        default:
            memset (dev->dev_addr, 0, 6);
            break;
        }
    } else
    {
        memset (dev->dev_addr, 0, 6);
    }

    hdlc->xmit = c4_linux_xmit;

    dev->netdev_ops = &chan_ops;
    /*
     * The native hdlc stack calls this 'attach' routine during
     * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
     * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
     * routine is actually registered or not, we supply a dummy routine which
     * does nothing (since encoding and parity are setup for our driver via a
     * special configuration application).
     */

    hdlc->attach = chan_attach_noop;

    rtnl_unlock ();                 /* needed due to Ioctl calling sequence */
    ret = register_hdlc_device (dev);
    /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
    dev->tx_queue_len = MAX_DEFAULT_IFQLEN;

    rtnl_lock ();                   /* needed due to Ioctl calling sequence */
    if (ret)
    {
        if (cxt1e1_log_level >= LOG_WARN)
            pr_info("%s: create_chan[%d] registration error = %d.\n",
                    ci->devname, cp->channum, ret);
        free_netdev (dev);          /* cleanup */
        return 0;                   /* failed to register */
    }
    return dev;
}