linux/drivers/staging/cxt1e1/hwprobe.c
<<
>>
Prefs
   1/* Copyright (C) 2007  One Stop Systems
   2 * Copyright (C) 2003-2005  SBE, Inc.
   3 *
   4 *   This program is free software; you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation; either version 2 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 */
  14
  15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  16
  17#include <linux/netdevice.h>
  18#include <linux/hdlc.h>
  19#include <linux/if_arp.h>
  20#include <asm/uaccess.h>
  21#include <linux/rtnetlink.h>
  22#include <linux/pci.h>
  23#include "pmcc4_sysdep.h"
  24#include "sbecom_inline_linux.h"
  25#include "libsbew.h"
  26#include "pmcc4_private.h"
  27#include "pmcc4.h"
  28#include "pmcc4_ioctls.h"
  29#include "pmc93x6_eeprom.h"
  30#ifdef CONFIG_PROC_FS
  31#include "sbeproc.h"
  32#endif
  33
  34extern int  cxt1e1_log_level;
  35extern int  error_flag;
  36extern int  drvr_state;
  37
  38/* forward references */
  39void        c4_stopwd (ci_t *);
  40struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
  41
  42
  43struct s_hdw_info hdw_info[MAX_BOARDS];
  44
  45
  46void        __init
  47show_two (hdw_info_t *hi, int brdno)
  48{
  49    ci_t       *ci;
  50    struct pci_dev *pdev;
  51    char       *bid;
  52    char       *bp, banner[80];
  53    char        sn[6];
  54
  55    bp = banner;
  56    memset (banner, 0, 80);         /* clear print buffer */
  57
  58    ci = (ci_t *)(netdev_priv(hi->ndev));
  59    bid = sbeid_get_bdname (ci);
  60    switch (hi->promfmt)
  61    {
  62    case PROM_FORMAT_TYPE1:
  63        memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
  64        break;
  65    case PROM_FORMAT_TYPE2:
  66        memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
  67        break;
  68    default:
  69        memset (sn, 0, 6);
  70        break;
  71    }
  72
  73    sprintf (banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
  74             hi->devname, bid,
  75             ((sn[3] << 16) & 0xff0000) |
  76              ((sn[4] << 8) & 0x00ff00) |
  77              (sn[5] & 0x0000ff),
  78             (u_int8_t) hi->revid[0]);
  79
  80    pr_info("%s\n", banner);
  81
  82    pdev = hi->pdev[0];
  83    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
  84            hi->devname, "MUSYCC",
  85            (unsigned long) hi->addr_mapped[0], hi->addr[0],
  86            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
  87            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
  88
  89    pdev = hi->pdev[1];
  90    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
  91            hi->devname, "EBUS  ",
  92            (unsigned long) hi->addr_mapped[1], hi->addr[1],
  93            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
  94            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
  95}
  96
  97
  98void        __init
  99hdw_sn_get (hdw_info_t *hi, int brdno)
 100{
 101    /* obtain hardware EEPROM information */
 102    long        addr;
 103
 104    addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
 105
 106    /* read EEPROM with largest known format size... */
 107    pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
 108
 109#if 0
 110    {
 111        unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
 112
 113        pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 114                *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
 115        pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 116                *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
 117        pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 118                *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
 119        pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 120                *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
 121        pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 122                *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
 123        pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
 124                *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
 125    }
 126#endif
 127#if 0
 128    pr_info("sn: %x %x %x %x %x %x\n",
 129            hi->mfg_info.Serial[0],
 130            hi->mfg_info.Serial[1],
 131            hi->mfg_info.Serial[2],
 132            hi->mfg_info.Serial[3],
 133            hi->mfg_info.Serial[4],
 134            hi->mfg_info.Serial[5]);
 135#endif
 136
 137    if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
 138    {
 139        /* bad crc, data is suspect */
 140        if (cxt1e1_log_level >= LOG_WARN)
 141            pr_info("%s: EEPROM cksum error\n", hi->devname);
 142        hi->mfg_info_sts = EEPROM_CRCERR;
 143    } else
 144        hi->mfg_info_sts = EEPROM_OK;
 145}
 146
 147
 148void        __init
 149prep_hdw_info (void)
 150{
 151    hdw_info_t *hi;
 152    int         i;
 153
 154    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 155    {
 156        hi->pci_busno = 0xff;
 157        hi->pci_slot = 0xff;
 158        hi->pci_pin[0] = 0;
 159        hi->pci_pin[1] = 0;
 160        hi->ndev = 0;
 161        hi->addr[0] = 0L;
 162        hi->addr[1] = 0L;
 163        hi->addr_mapped[0] = 0L;
 164        hi->addr_mapped[1] = 0L;
 165    }
 166}
 167
 168void
 169cleanup_ioremap (void)
 170{
 171    hdw_info_t *hi;
 172    int         i;
 173
 174    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 175    {
 176        if (hi->pci_slot == 0xff)
 177            break;
 178        if (hi->addr_mapped[0])
 179        {
 180            iounmap ((void *) (hi->addr_mapped[0]));
 181            release_mem_region ((long) hi->addr[0], hi->len[0]);
 182            hi->addr_mapped[0] = 0;
 183        }
 184        if (hi->addr_mapped[1])
 185        {
 186            iounmap ((void *) (hi->addr_mapped[1]));
 187            release_mem_region ((long) hi->addr[1], hi->len[1]);
 188            hi->addr_mapped[1] = 0;
 189        }
 190    }
 191}
 192
 193
 194void
 195cleanup_devs (void)
 196{
 197    hdw_info_t *hi;
 198    int         i;
 199
 200    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 201    {
 202        if (hi->pci_slot == 0xff || !hi->ndev)
 203            break;
 204        c4_stopwd(netdev_priv(hi->ndev));
 205#ifdef CONFIG_PROC_FS
 206        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
 207#endif
 208        unregister_netdev (hi->ndev);
 209        free_irq (hi->pdev[0]->irq, hi->ndev);
 210#ifdef CONFIG_SBE_PMCC4_NCOMM
 211        free_irq (hi->pdev[1]->irq, hi->ndev);
 212#endif
 213        OS_kfree (hi->ndev);
 214    }
 215}
 216
 217
 218static int  __init
 219c4_hdw_init (struct pci_dev *pdev, int found)
 220{
 221    hdw_info_t *hi;
 222    int         i;
 223    int         fun, slot;
 224    unsigned char busno = 0xff;
 225
 226    /* our MUSYCC chip supports two functions, 0 & 1 */
 227    if ((fun = PCI_FUNC (pdev->devfn)) > 1)
 228    {
 229        pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
 230        return 0;
 231    }
 232    if (pdev->bus)                  /* obtain bus number */
 233        busno = pdev->bus->number;
 234    else
 235        busno = 0;                  /* default for system PCI inconsistency */
 236    slot = pdev->devfn & ~0x07;
 237
 238    /*
 239     * Functions 0 & 1 for a given board (identified by same bus(busno) and
 240     * slot(slot)) are placed into the same 'hardware' structure.  The first
 241     * part of the board's functionality will be placed into an unpopulated
 242     * element, identified by "slot==(0xff)".  The second part of a board's
 243     * functionality will match the previously loaded slot/busno.
 244     */
 245    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 246    {
 247        /*
 248         * match with board's first found interface, otherwise this is first
 249         * found
 250         */
 251        if ((hi->pci_slot == 0xff) ||   /* new board */
 252            ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
 253            break;                  /* found for-loop exit */
 254    }
 255    if (i == MAX_BOARDS)            /* no match in above loop means MAX
 256                                     * exceeded */
 257    {
 258        pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
 259        return 0;
 260    }
 261    if (pdev->bus)
 262        hi->pci_busno = pdev->bus->number;
 263    else
 264        hi->pci_busno = 0;          /* default for system PCI inconsistency */
 265    hi->pci_slot = slot;
 266    pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
 267    pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
 268    hi->bus = pdev->bus;
 269    hi->addr[fun] = pci_resource_start (pdev, 0);
 270    hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
 271    hi->pdev[fun] = pdev;
 272
 273    {
 274        /*
 275         * create device name from module name, plus add the appropriate
 276         * board number
 277         */
 278        char       *cp = hi->devname;
 279
 280        strcpy (cp, KBUILD_MODNAME);
 281        cp += strlen (cp);          /* reposition */
 282        *cp++ = '-';
 283        *cp++ = '0' + (found / 2);  /* there are two found interfaces per
 284                                     * board */
 285        *cp = 0;                    /* termination */
 286    }
 287
 288    return 1;
 289}
 290
 291
 292status_t    __init
 293c4hw_attach_all (void)
 294{
 295    hdw_info_t *hi;
 296    struct pci_dev *pdev = NULL;
 297    int         found = 0, i, j;
 298
 299    error_flag = 0;
 300    prep_hdw_info ();
 301    /*** scan PCI bus for all possible boards */
 302    while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
 303                                    PCI_DEVICE_ID_CN8474,
 304                                    pdev)))
 305    {
 306        if (c4_hdw_init (pdev, found))
 307            found++;
 308    }
 309    if (!found)
 310    {
 311        pr_warning("No boards found\n");
 312        return ENODEV;
 313    }
 314    /* sanity check for consistent hardware found */
 315    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 316    {
 317        if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
 318        {
 319            pr_warning("%s: something very wrong with pci_get_device\n",
 320                       hi->devname);
 321            return EIO;
 322        }
 323    }
 324    /* bring board's memory regions on/line */
 325    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 326    {
 327        if (hi->pci_slot == 0xff)
 328            break;
 329        for (j = 0; j < 2; j++)
 330        {
 331            if (request_mem_region (hi->addr[j], hi->len[j], hi->devname) == 0)
 332            {
 333                pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
 334                           hi->devname, hi->addr[j], hi->len[j]);
 335                cleanup_ioremap ();
 336                return ENOMEM;
 337            }
 338            hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
 339            if (!hi->addr_mapped[j])
 340            {
 341                pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
 342                           hi->devname, hi->addr[j], hi->len[j]);
 343                cleanup_ioremap ();
 344                return ENOMEM;
 345            }
 346#ifdef SBE_MAP_DEBUG
 347            pr_warning("%s: io remapped from phys %x to virt %x\n",
 348                       hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
 349#endif
 350        }
 351    }
 352
 353    drvr_state = SBE_DRVR_AVAILABLE;
 354
 355    /* Have now memory mapped all boards.  Now allow board's access to system */
 356    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
 357    {
 358        if (hi->pci_slot == 0xff)
 359            break;
 360        if (pci_enable_device (hi->pdev[0]) ||
 361            pci_enable_device (hi->pdev[1]))
 362        {
 363            drvr_state = SBE_DRVR_DOWN;
 364            pr_warning("%s: failed to enable card %d slot %d\n",
 365                       hi->devname, i, hi->pci_slot);
 366            cleanup_devs ();
 367            cleanup_ioremap ();
 368            return EIO;
 369        }
 370        pci_set_master (hi->pdev[0]);
 371        pci_set_master (hi->pdev[1]);
 372        if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
 373                                     (long) hi->addr_mapped[1],
 374                                     hi->pdev[0]->irq,
 375                                     hi->pdev[1]->irq)))
 376        {
 377            drvr_state = SBE_DRVR_DOWN;
 378            cleanup_ioremap ();
 379            /* NOTE: c4_add_dev() does its own device cleanup */
 380#if 0
 381            cleanup_devs ();
 382#endif
 383            return error_flag;      /* error_flag set w/in add_dev() */
 384        }
 385        show_two (hi, i);           /* displays found information */
 386    }
 387    return 0;
 388}
 389
 390/***  End-of-File  ***/
 391