linux/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
<<
>>
Prefs
   1/*---------------------------------------------------------------------------
   2   FT1000 driver for Flarion Flash OFDM NIC Device
   3
   4   Copyright (C) 2002 Flarion Technologies, All rights reserved.
   5   Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
   6   Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
   7
   8   This program is free software; you can redistribute it and/or modify it
   9   under the terms of the GNU General Public License as published by the Free
  10   Software Foundation; either version 2 of the License, or (at your option) any
  11   later version. This program is distributed in the hope that it will be useful,
  12   but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14   more details. You should have received a copy of the GNU General Public
  15   License along with this program; if not, write to the
  16   Free Software Foundation, Inc., 59 Temple Place -
  17   Suite 330, Boston, MA 02111-1307, USA.
  18-----------------------------------------------------------------------------*/
  19
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22#include <linux/proc_fs.h>
  23
  24#include <linux/sched.h>
  25#include <linux/ptrace.h>
  26#include <linux/slab.h>
  27#include <linux/string.h>
  28#include <linux/timer.h>
  29#include <linux/interrupt.h>
  30#include <linux/in.h>
  31#include <asm/io.h>
  32#include <asm/system.h>
  33#include <asm/bitops.h>
  34
  35#include <linux/netdevice.h>
  36#include <linux/etherdevice.h>
  37#include <linux/skbuff.h>
  38#include <linux/if_arp.h>
  39#include <linux/ioport.h>
  40#include <linux/wait.h>
  41#include <linux/vmalloc.h>
  42
  43#include <linux/firmware.h>
  44#include <linux/ethtool.h>
  45
  46#include <pcmcia/cistpl.h>
  47#include <pcmcia/cisreg.h>
  48#include <pcmcia/ds.h>
  49
  50#ifdef FT_DEBUG
  51#define DEBUG(n, args...) printk(KERN_DEBUG args);
  52#else
  53#define DEBUG(n, args...)
  54#endif
  55
  56#include <linux/delay.h>
  57#include "ft1000.h"
  58
  59static const struct firmware *fw_entry;
  60
  61static void ft1000_hbchk(u_long data);
  62static struct timer_list poll_timer = {
  63      .function = ft1000_hbchk
  64};
  65
  66static u16 cmdbuffer[1024];
  67static u8 tempbuffer[1600];
  68static u8 ft1000_card_present = 0;
  69static u8 flarion_ft1000_cnt = 0;
  70
  71static irqreturn_t ft1000_interrupt(int irq, void *dev_id);
  72static void ft1000_enable_interrupts(struct net_device *dev);
  73static void ft1000_disable_interrupts(struct net_device *dev);
  74
  75/* new kernel */
  76MODULE_AUTHOR("");
  77MODULE_DESCRIPTION
  78    ("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
  79MODULE_LICENSE("GPL");
  80MODULE_SUPPORTED_DEVICE("FT1000");
  81
  82#define MAX_RCV_LOOP   100
  83
  84//---------------------------------------------------------------------------
  85//
  86// Function:   ft1000_read_fifo_len
  87// Description: This function will read the ASIC Uplink FIFO status register
  88//             which will return the number of bytes remaining in the Uplink FIFO.
  89//             Sixteen bytes are subtracted to make sure that the ASIC does not
  90//             reach its threshold.
  91// Input:
  92//     dev    - network device structure
  93// Output:
  94//     value  - number of bytes available in the ASIC Uplink FIFO.
  95//
  96//---------------------------------------------------------------------------
  97static inline u16 ft1000_read_fifo_len(struct net_device *dev)
  98{
  99        struct ft1000_info *info = netdev_priv(dev);
 100
 101        if (info->AsicID == ELECTRABUZZ_ID) {
 102                return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
 103        } else {
 104                return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16);
 105        }
 106}
 107
 108//---------------------------------------------------------------------------
 109//
 110// Function:   ft1000_read_dpram
 111// Description: This function will read the specific area of dpram
 112//             (Electrabuzz ASIC only)
 113// Input:
 114//     dev    - device structure
 115//     offset - index of dpram
 116// Output:
 117//     value  - value of dpram
 118//
 119//---------------------------------------------------------------------------
 120u16 ft1000_read_dpram(struct net_device * dev, int offset)
 121{
 122        struct ft1000_info *info = netdev_priv(dev);
 123        unsigned long flags;
 124        u16 data;
 125
 126        // Provide mutual exclusive access while reading ASIC registers.
 127        spin_lock_irqsave(&info->dpram_lock, flags);
 128        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 129        data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
 130        spin_unlock_irqrestore(&info->dpram_lock, flags);
 131
 132        return (data);
 133}
 134
 135//---------------------------------------------------------------------------
 136//
 137// Function:   ft1000_write_dpram
 138// Description: This function will write to a specific area of dpram
 139//             (Electrabuzz ASIC only)
 140// Input:
 141//     dev    - device structure
 142//     offset - index of dpram
 143//     value  - value to write
 144// Output:
 145//     none.
 146//
 147//---------------------------------------------------------------------------
 148static inline void ft1000_write_dpram(struct net_device *dev,
 149                                          int offset, u16 value)
 150{
 151        struct ft1000_info *info = netdev_priv(dev);
 152        unsigned long flags;
 153
 154        // Provide mutual exclusive access while reading ASIC registers.
 155        spin_lock_irqsave(&info->dpram_lock, flags);
 156        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 157        ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value);
 158        spin_unlock_irqrestore(&info->dpram_lock, flags);
 159}
 160
 161//---------------------------------------------------------------------------
 162//
 163// Function:   ft1000_read_dpram_mag_16
 164// Description: This function will read the specific area of dpram
 165//             (Magnemite ASIC only)
 166// Input:
 167//     dev    - device structure
 168//     offset - index of dpram
 169// Output:
 170//     value  - value of dpram
 171//
 172//---------------------------------------------------------------------------
 173u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
 174{
 175        struct ft1000_info *info = netdev_priv(dev);
 176        unsigned long flags;
 177        u16 data;
 178
 179        // Provide mutual exclusive access while reading ASIC registers.
 180        spin_lock_irqsave(&info->dpram_lock, flags);
 181        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 182        // check if we want to read upper or lower 32-bit word
 183        if (Index) {
 184                data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL);
 185        } else {
 186                data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH);
 187        }
 188        spin_unlock_irqrestore(&info->dpram_lock, flags);
 189
 190        return (data);
 191}
 192
 193//---------------------------------------------------------------------------
 194//
 195// Function:   ft1000_write_dpram_mag_16
 196// Description: This function will write to a specific area of dpram
 197//             (Magnemite ASIC only)
 198// Input:
 199//     dev    - device structure
 200//     offset - index of dpram
 201//     value  - value to write
 202// Output:
 203//     none.
 204//
 205//---------------------------------------------------------------------------
 206static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
 207                                                 int offset, u16 value, int Index)
 208{
 209        struct ft1000_info *info = netdev_priv(dev);
 210        unsigned long flags;
 211
 212        // Provide mutual exclusive access while reading ASIC registers.
 213        spin_lock_irqsave(&info->dpram_lock, flags);
 214        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 215        if (Index) {
 216                ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value);
 217        } else {
 218                ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value);
 219        }
 220        spin_unlock_irqrestore(&info->dpram_lock, flags);
 221}
 222
 223//---------------------------------------------------------------------------
 224//
 225// Function:   ft1000_read_dpram_mag_32
 226// Description: This function will read the specific area of dpram
 227//             (Magnemite ASIC only)
 228// Input:
 229//     dev    - device structure
 230//     offset - index of dpram
 231// Output:
 232//     value  - value of dpram
 233//
 234//---------------------------------------------------------------------------
 235u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
 236{
 237        struct ft1000_info *info = netdev_priv(dev);
 238        unsigned long flags;
 239        u32 data;
 240
 241        // Provide mutual exclusive access while reading ASIC registers.
 242        spin_lock_irqsave(&info->dpram_lock, flags);
 243        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 244        data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL);
 245        spin_unlock_irqrestore(&info->dpram_lock, flags);
 246
 247        return (data);
 248}
 249
 250//---------------------------------------------------------------------------
 251//
 252// Function:   ft1000_write_dpram_mag_32
 253// Description: This function will write to a specific area of dpram
 254//             (Magnemite ASIC only)
 255// Input:
 256//     dev    - device structure
 257//     offset - index of dpram
 258//     value  - value to write
 259// Output:
 260//     none.
 261//
 262//---------------------------------------------------------------------------
 263void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
 264{
 265        struct ft1000_info *info = netdev_priv(dev);
 266        unsigned long flags;
 267
 268        // Provide mutual exclusive access while reading ASIC registers.
 269        spin_lock_irqsave(&info->dpram_lock, flags);
 270        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
 271        outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL);
 272        spin_unlock_irqrestore(&info->dpram_lock, flags);
 273}
 274
 275//---------------------------------------------------------------------------
 276//
 277// Function:   ft1000_enable_interrupts
 278// Description: This function will enable interrupts base on the current interrupt mask.
 279// Input:
 280//     dev    - device structure
 281// Output:
 282//     None.
 283//
 284//---------------------------------------------------------------------------
 285static void ft1000_enable_interrupts(struct net_device *dev)
 286{
 287        u16 tempword;
 288
 289        DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n");
 290        ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
 291        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
 292        DEBUG(1,
 293                  "ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n",
 294                  tempword);
 295}
 296
 297//---------------------------------------------------------------------------
 298//
 299// Function:   ft1000_disable_interrupts
 300// Description: This function will disable all interrupts.
 301// Input:
 302//     dev    - device structure
 303// Output:
 304//     None.
 305//
 306//---------------------------------------------------------------------------
 307static void ft1000_disable_interrupts(struct net_device *dev)
 308{
 309        u16 tempword;
 310
 311        DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n");
 312        ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL);
 313        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
 314        DEBUG(1,
 315                  "ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n",
 316                  tempword);
 317}
 318
 319//---------------------------------------------------------------------------
 320//
 321// Function:   ft1000_reset_asic
 322// Description: This function will call the Card Service function to reset the
 323//             ASIC.
 324// Input:
 325//     dev    - device structure
 326// Output:
 327//     none
 328//
 329//---------------------------------------------------------------------------
 330static void ft1000_reset_asic(struct net_device *dev)
 331{
 332        struct ft1000_info *info = netdev_priv(dev);
 333        u16 tempword;
 334
 335        DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n");
 336
 337        (*info->ft1000_reset) (info->link);
 338
 339        // Let's use the register provided by the Magnemite ASIC to reset the
 340        // ASIC and DSP.
 341        if (info->AsicID == MAGNEMITE_ID) {
 342                ft1000_write_reg(dev, FT1000_REG_RESET,
 343                                 (DSP_RESET_BIT | ASIC_RESET_BIT));
 344        }
 345        mdelay(1);
 346        if (info->AsicID == ELECTRABUZZ_ID) {
 347                // set watermark to -1 in order to not generate an interrupt
 348                ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff);
 349        } else {
 350                // set watermark to -1 in order to not generate an interrupt
 351                ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff);
 352        }
 353        // clear interrupts
 354        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
 355        DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
 356        ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
 357        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
 358        DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
 359
 360}
 361
 362//---------------------------------------------------------------------------
 363//
 364// Function:   ft1000_reset_card
 365// Description: This function will reset the card
 366// Input:
 367//     dev    - device structure
 368// Output:
 369//     status - false (card reset fail)
 370//              true  (card reset successful)
 371//
 372//---------------------------------------------------------------------------
 373static int ft1000_reset_card(struct net_device *dev)
 374{
 375        struct ft1000_info *info = netdev_priv(dev);
 376        u16 tempword;
 377        int i;
 378        unsigned long flags;
 379        struct prov_record *ptr;
 380
 381        DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n");
 382
 383        info->CardReady = 0;
 384        info->ProgConStat = 0;
 385        info->squeseqnum = 0;
 386        ft1000_disable_interrupts(dev);
 387
 388//      del_timer(&poll_timer);
 389
 390        // Make sure we free any memory reserve for provisioning
 391        while (list_empty(&info->prov_list) == 0) {
 392                DEBUG(0,
 393                          "ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
 394                ptr = list_entry(info->prov_list.next, struct prov_record, list);
 395                list_del(&ptr->list);
 396                kfree(ptr->pprov_data);
 397                kfree(ptr);
 398        }
 399
 400        if (info->AsicID == ELECTRABUZZ_ID) {
 401                DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting DSP\n");
 402                ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
 403        } else {
 404                DEBUG(1,
 405                          "ft1000_hw:ft1000_reset_card:resetting ASIC and DSP\n");
 406                ft1000_write_reg(dev, FT1000_REG_RESET,
 407                                 (DSP_RESET_BIT | ASIC_RESET_BIT));
 408        }
 409
 410        // Copy DSP session record into info block if this is not a coldstart
 411        if (ft1000_card_present == 1) {
 412                spin_lock_irqsave(&info->dpram_lock, flags);
 413                if (info->AsicID == ELECTRABUZZ_ID) {
 414                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 415                                         FT1000_DPRAM_RX_BASE);
 416                        for (i = 0; i < MAX_DSP_SESS_REC; i++) {
 417                                info->DSPSess.Rec[i] =
 418                                        ft1000_read_reg(dev,
 419                                                        FT1000_REG_DPRAM_DATA);
 420                        }
 421                } else {
 422                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 423                                         FT1000_DPRAM_MAG_RX_BASE);
 424                        for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
 425                                info->DSPSess.MagRec[i] =
 426                                        inl(dev->base_addr + FT1000_REG_MAG_DPDATA);
 427                        }
 428                }
 429                spin_unlock_irqrestore(&info->dpram_lock, flags);
 430        }
 431
 432        DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting ASIC\n");
 433        mdelay(10);
 434        //reset ASIC
 435        ft1000_reset_asic(dev);
 436
 437        DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n");
 438
 439        if (info->AsicID == MAGNEMITE_ID) {
 440                // Put dsp in reset and take ASIC out of reset
 441                DEBUG(0,
 442                          "ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n");
 443                ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
 444
 445                // Setting MAGNEMITE ASIC to big endian mode
 446                ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE);
 447                // Download bootloader
 448                card_bootload(dev);
 449
 450                // Take DSP out of reset
 451                ft1000_write_reg(dev, FT1000_REG_RESET, 0);
 452                // FLARION_DSP_ACTIVE;
 453                mdelay(10);
 454                DEBUG(0, "ft1000_hw:ft1000_reset_card:Take DSP out of reset\n");
 455
 456                // Wait for 0xfefe indicating dsp ready before starting download
 457                for (i = 0; i < 50; i++) {
 458                        tempword =
 459                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE,
 460                                                         FT1000_MAG_DPRAM_FEFE_INDX);
 461                        if (tempword == 0xfefe) {
 462                                break;
 463                        }
 464                        mdelay(20);
 465                }
 466
 467                if (i == 50) {
 468                        DEBUG(0,
 469                                  "ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n");
 470                        return false;
 471                }
 472
 473        } else {
 474                // Take DSP out of reset
 475                ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT);
 476                mdelay(10);
 477        }
 478
 479        if (card_download(dev, fw_entry->data, fw_entry->size)) {
 480                DEBUG(1, "card download unsuccessful\n");
 481                return false;
 482        } else {
 483                DEBUG(1, "card download successful\n");
 484        }
 485
 486        mdelay(10);
 487
 488        if (info->AsicID == ELECTRABUZZ_ID) {
 489                // Need to initialize the FIFO length counter to zero in order to sync up
 490                // with the DSP
 491                info->fifo_cnt = 0;
 492                ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
 493                // Initialize DSP heartbeat area to ho
 494                ft1000_write_dpram(dev, FT1000_HI_HO, ho);
 495                tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
 496                DEBUG(1, "ft1000_hw:ft1000_reset_asic:hi_ho value = 0x%x\n",
 497                          tempword);
 498        } else {
 499                // Initialize DSP heartbeat area to ho
 500                ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag,
 501                                          FT1000_MAG_HI_HO_INDX);
 502                tempword =
 503                        ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO,
 504                                                 FT1000_MAG_HI_HO_INDX);
 505                DEBUG(1, "ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n",
 506                          tempword);
 507        }
 508
 509        info->CardReady = 1;
 510        ft1000_enable_interrupts(dev);
 511
 512        /* Schedule heartbeat process to run every 2 seconds */
 513//      poll_timer.expires = jiffies + (2*HZ);
 514//      poll_timer.data = (u_long)dev;
 515//      add_timer(&poll_timer);
 516
 517        return true;
 518
 519}
 520
 521//---------------------------------------------------------------------------
 522//
 523// Function:   ft1000_chkcard
 524// Description: This function will check if the device is presently available on
 525//             the system.
 526// Input:
 527//     dev    - device structure
 528// Output:
 529//     status - false (device is not present)
 530//              true  (device is present)
 531//
 532//---------------------------------------------------------------------------
 533static int ft1000_chkcard(struct net_device *dev)
 534{
 535        u16 tempword;
 536
 537        // Mask register is used to check for device presence since it is never
 538        // set to zero.
 539        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
 540        if (tempword == 0) {
 541                DEBUG(1,
 542                          "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
 543                return false;
 544        }
 545        // The system will return the value of 0xffff for the version register
 546        // if the device is not present.
 547        tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
 548        if (tempword == 0xffff) {
 549                DEBUG(1,
 550                          "ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
 551                return false;
 552        }
 553        return true;
 554}
 555
 556
 557//---------------------------------------------------------------------------
 558//
 559// Function:   ft1000_hbchk
 560// Description: This function will perform the heart beat check of the DSP as
 561//             well as the ASIC.
 562// Input:
 563//     dev    - device structure
 564// Output:
 565//     none
 566//
 567//---------------------------------------------------------------------------
 568static void ft1000_hbchk(u_long data)
 569{
 570        struct net_device *dev = (struct net_device *)data;
 571
 572        struct ft1000_info *info;
 573        u16 tempword;
 574
 575        info = netdev_priv(dev);
 576
 577        if (info->CardReady == 1) {
 578                // Perform dsp heartbeat check
 579                if (info->AsicID == ELECTRABUZZ_ID) {
 580                        tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
 581                } else {
 582                        tempword =
 583                                ntohs(ft1000_read_dpram_mag_16
 584                                  (dev, FT1000_MAG_HI_HO,
 585                                   FT1000_MAG_HI_HO_INDX));
 586                }
 587                DEBUG(1, "ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n",
 588                          tempword);
 589                // Let's perform another check if ho is not detected
 590                if (tempword != ho) {
 591                        if (info->AsicID == ELECTRABUZZ_ID) {
 592                                tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
 593                        }
 594                        else {
 595                                tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
 596                        }
 597                }
 598                if (tempword != ho) {
 599                        printk(KERN_INFO
 600                                   "ft1000: heartbeat failed - no ho detected\n");
 601                        if (info->AsicID == ELECTRABUZZ_ID) {
 602                                info->DSP_TIME[0] =
 603                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
 604                                info->DSP_TIME[1] =
 605                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
 606                                info->DSP_TIME[2] =
 607                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
 608                                info->DSP_TIME[3] =
 609                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
 610                        } else {
 611                                info->DSP_TIME[0] =
 612                                        ft1000_read_dpram_mag_16(dev,
 613                                                                 FT1000_MAG_DSP_TIMER0,
 614                                                                 FT1000_MAG_DSP_TIMER0_INDX);
 615                                info->DSP_TIME[1] =
 616                                        ft1000_read_dpram_mag_16(dev,
 617                                                                 FT1000_MAG_DSP_TIMER1,
 618                                                                 FT1000_MAG_DSP_TIMER1_INDX);
 619                                info->DSP_TIME[2] =
 620                                        ft1000_read_dpram_mag_16(dev,
 621                                                                 FT1000_MAG_DSP_TIMER2,
 622                                                                 FT1000_MAG_DSP_TIMER2_INDX);
 623                                info->DSP_TIME[3] =
 624                                        ft1000_read_dpram_mag_16(dev,
 625                                                                 FT1000_MAG_DSP_TIMER3,
 626                                                                 FT1000_MAG_DSP_TIMER3_INDX);
 627                        }
 628                        info->DrvErrNum = DSP_HB_INFO;
 629                        if (ft1000_reset_card(dev) == 0) {
 630                                printk(KERN_INFO
 631                                           "ft1000: Hardware Failure Detected - PC Card disabled\n");
 632                                info->ProgConStat = 0xff;
 633                                return;
 634                        }
 635                        /* Schedule this module to run every 2 seconds */
 636                        poll_timer.expires = jiffies + (2*HZ);
 637                        poll_timer.data = (u_long)dev;
 638                        add_timer(&poll_timer);
 639                        return;
 640                }
 641
 642                tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
 643                // Let's check doorbell again if fail
 644                if (tempword & FT1000_DB_HB) {
 645                        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
 646                }
 647                if (tempword & FT1000_DB_HB) {
 648                        printk(KERN_INFO
 649                                   "ft1000: heartbeat doorbell not clear by firmware\n");
 650                        if (info->AsicID == ELECTRABUZZ_ID) {
 651                                info->DSP_TIME[0] =
 652                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
 653                                info->DSP_TIME[1] =
 654                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
 655                                info->DSP_TIME[2] =
 656                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
 657                                info->DSP_TIME[3] =
 658                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
 659                        } else {
 660                                info->DSP_TIME[0] =
 661                                        ft1000_read_dpram_mag_16(dev,
 662                                                                 FT1000_MAG_DSP_TIMER0,
 663                                                                 FT1000_MAG_DSP_TIMER0_INDX);
 664                                info->DSP_TIME[1] =
 665                                        ft1000_read_dpram_mag_16(dev,
 666                                                                 FT1000_MAG_DSP_TIMER1,
 667                                                                 FT1000_MAG_DSP_TIMER1_INDX);
 668                                info->DSP_TIME[2] =
 669                                        ft1000_read_dpram_mag_16(dev,
 670                                                                 FT1000_MAG_DSP_TIMER2,
 671                                                                 FT1000_MAG_DSP_TIMER2_INDX);
 672                                info->DSP_TIME[3] =
 673                                        ft1000_read_dpram_mag_16(dev,
 674                                                                 FT1000_MAG_DSP_TIMER3,
 675                                                                 FT1000_MAG_DSP_TIMER3_INDX);
 676                        }
 677                        info->DrvErrNum = DSP_HB_INFO;
 678                        if (ft1000_reset_card(dev) == 0) {
 679                                printk(KERN_INFO
 680                                           "ft1000: Hardware Failure Detected - PC Card disabled\n");
 681                                info->ProgConStat = 0xff;
 682                                return;
 683                        }
 684                        /* Schedule this module to run every 2 seconds */
 685                        poll_timer.expires = jiffies + (2*HZ);
 686                        poll_timer.data = (u_long)dev;
 687                        add_timer(&poll_timer);
 688                        return;
 689                }
 690                // Set dedicated area to hi and ring appropriate doorbell according
 691                // to hi/ho heartbeat protocol
 692                if (info->AsicID == ELECTRABUZZ_ID) {
 693                        ft1000_write_dpram(dev, FT1000_HI_HO, hi);
 694                } else {
 695                        ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag,
 696                                                  FT1000_MAG_HI_HO_INDX);
 697                }
 698
 699                if (info->AsicID == ELECTRABUZZ_ID) {
 700                        tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
 701                } else {
 702                        tempword =
 703                                ntohs(ft1000_read_dpram_mag_16
 704                                  (dev, FT1000_MAG_HI_HO,
 705                                   FT1000_MAG_HI_HO_INDX));
 706                }
 707        // Let's write hi again if fail
 708                if (tempword != hi) {
 709                        if (info->AsicID == ELECTRABUZZ_ID) {
 710                                ft1000_write_dpram(dev, FT1000_HI_HO, hi);
 711                        }
 712                        else {
 713                                ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX);
 714                        }
 715
 716                        if (info->AsicID == ELECTRABUZZ_ID) {
 717                                tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
 718                        }
 719                        else {
 720                                tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
 721                        }
 722
 723                }
 724
 725                if (tempword != hi) {
 726                        printk(KERN_INFO
 727                                   "ft1000: heartbeat failed - cannot write hi into DPRAM\n");
 728                        if (info->AsicID == ELECTRABUZZ_ID) {
 729                                info->DSP_TIME[0] =
 730                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
 731                                info->DSP_TIME[1] =
 732                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
 733                                info->DSP_TIME[2] =
 734                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
 735                                info->DSP_TIME[3] =
 736                                        ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
 737                        } else {
 738                                info->DSP_TIME[0] =
 739                                        ft1000_read_dpram_mag_16(dev,
 740                                                                 FT1000_MAG_DSP_TIMER0,
 741                                                                 FT1000_MAG_DSP_TIMER0_INDX);
 742                                info->DSP_TIME[1] =
 743                                        ft1000_read_dpram_mag_16(dev,
 744                                                                 FT1000_MAG_DSP_TIMER1,
 745                                                                 FT1000_MAG_DSP_TIMER1_INDX);
 746                                info->DSP_TIME[2] =
 747                                        ft1000_read_dpram_mag_16(dev,
 748                                                                 FT1000_MAG_DSP_TIMER2,
 749                                                                 FT1000_MAG_DSP_TIMER2_INDX);
 750                                info->DSP_TIME[3] =
 751                                        ft1000_read_dpram_mag_16(dev,
 752                                                                 FT1000_MAG_DSP_TIMER3,
 753                                                                 FT1000_MAG_DSP_TIMER3_INDX);
 754                        }
 755                        info->DrvErrNum = DSP_HB_INFO;
 756                        if (ft1000_reset_card(dev) == 0) {
 757                                printk(KERN_INFO
 758                                           "ft1000: Hardware Failure Detected - PC Card disabled\n");
 759                                info->ProgConStat = 0xff;
 760                                return;
 761                        }
 762                        /* Schedule this module to run every 2 seconds */
 763                        poll_timer.expires = jiffies + (2*HZ);
 764                        poll_timer.data = (u_long)dev;
 765                        add_timer(&poll_timer);
 766                        return;
 767                }
 768                ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB);
 769
 770        }
 771
 772        /* Schedule this module to run every 2 seconds */
 773        poll_timer.expires = jiffies + (2 * HZ);
 774        poll_timer.data = (u_long) dev;
 775        add_timer(&poll_timer);
 776}
 777
 778//---------------------------------------------------------------------------
 779//
 780// Function:   ft1000_send_cmd
 781// Description:
 782// Input:
 783// Output:
 784//
 785//---------------------------------------------------------------------------
 786static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
 787{
 788        struct ft1000_info *info = netdev_priv(dev);
 789        int i;
 790        u16 tempword;
 791        unsigned long flags;
 792
 793        size += sizeof(struct pseudo_hdr);
 794        // check for odd byte and increment to 16-bit word align value
 795        if ((size & 0x0001)) {
 796                size++;
 797        }
 798        DEBUG(1, "FT1000:ft1000_send_cmd:total length = %d\n", size);
 799        DEBUG(1, "FT1000:ft1000_send_cmd:length = %d\n", ntohs(*ptempbuffer));
 800        // put message into slow queue area
 801        // All messages are in the form total_len + pseudo header + message body
 802        spin_lock_irqsave(&info->dpram_lock, flags);
 803
 804    // Make sure SLOWQ doorbell is clear
 805    tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
 806    i=0;
 807    while (tempword & FT1000_DB_DPRAM_TX) {
 808        mdelay(10);
 809        i++;
 810        if (i==10) {
 811            spin_unlock_irqrestore(&info->dpram_lock, flags);
 812            return;
 813        }
 814        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
 815    }
 816
 817        if (info->AsicID == ELECTRABUZZ_ID) {
 818                ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 819                                 FT1000_DPRAM_TX_BASE);
 820                // Write total length to dpram
 821                ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
 822                // Write pseudo header and messgae body
 823                for (i = 0; i < (size >> 1); i++) {
 824                        DEBUG(1, "FT1000:ft1000_send_cmd:data %d = 0x%x\n", i,
 825                                  *ptempbuffer);
 826                        tempword = htons(*ptempbuffer++);
 827                        ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword);
 828                }
 829        } else {
 830                ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 831                                 FT1000_DPRAM_MAG_TX_BASE);
 832                // Write total length to dpram
 833                ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size));
 834                // Write pseudo header and messgae body
 835                ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 836                                 FT1000_DPRAM_MAG_TX_BASE + 1);
 837                for (i = 0; i < (size >> 2); i++) {
 838                        DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
 839                                  *ptempbuffer);
 840                        outw(*ptempbuffer++,
 841                                 dev->base_addr + FT1000_REG_MAG_DPDATAL);
 842                        DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
 843                                  *ptempbuffer);
 844                        outw(*ptempbuffer++,
 845                                 dev->base_addr + FT1000_REG_MAG_DPDATAH);
 846                }
 847                DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
 848                outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL);
 849                DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
 850                outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH);
 851        }
 852        spin_unlock_irqrestore(&info->dpram_lock, flags);
 853
 854        // ring doorbell to notify DSP that we have a message ready
 855        ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX);
 856}
 857
 858//---------------------------------------------------------------------------
 859//
 860// Function:   ft1000_receive_cmd
 861// Description: This function will read a message from the dpram area.
 862// Input:
 863//    dev - network device structure
 864//    pbuffer - caller supply address to buffer
 865//    pnxtph - pointer to next pseudo header
 866// Output:
 867//   Status = 0 (unsuccessful)
 868//          = 1 (successful)
 869//
 870//---------------------------------------------------------------------------
 871static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
 872                                int maxsz, u16 *pnxtph)
 873{
 874        struct ft1000_info *info = netdev_priv(dev);
 875        u16 size;
 876        u16 *ppseudohdr;
 877        int i;
 878        u16 tempword;
 879        unsigned long flags;
 880
 881        if (info->AsicID == ELECTRABUZZ_ID) {
 882                size = ( ft1000_read_dpram(dev, *pnxtph) ) + sizeof(struct pseudo_hdr);
 883        } else {
 884                size =
 885                        ntohs(ft1000_read_dpram_mag_16
 886                          (dev, FT1000_MAG_PH_LEN,
 887                           FT1000_MAG_PH_LEN_INDX)) + sizeof(struct pseudo_hdr);
 888        }
 889        if (size > maxsz) {
 890                DEBUG(1,
 891                          "FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
 892                          size);
 893                return false;
 894        } else {
 895                ppseudohdr = (u16 *) pbuffer;
 896                spin_lock_irqsave(&info->dpram_lock, flags);
 897                if (info->AsicID == ELECTRABUZZ_ID) {
 898                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 899                                         FT1000_DPRAM_RX_BASE + 2);
 900                        for (i = 0; i <= (size >> 1); i++) {
 901                                tempword =
 902                                        ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
 903                                *pbuffer++ = ntohs(tempword);
 904                        }
 905                } else {
 906                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 907                                         FT1000_DPRAM_MAG_RX_BASE);
 908                        *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
 909                        DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
 910                        pbuffer++;
 911                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 912                                         FT1000_DPRAM_MAG_RX_BASE + 1);
 913                        for (i = 0; i <= (size >> 2); i++) {
 914                                *pbuffer =
 915                                        inw(dev->base_addr +
 916                                        FT1000_REG_MAG_DPDATAL);
 917                                pbuffer++;
 918                                *pbuffer =
 919                                        inw(dev->base_addr +
 920                                        FT1000_REG_MAG_DPDATAH);
 921                                pbuffer++;
 922                        }
 923                        //copy odd aligned word
 924                        *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
 925                        DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
 926                        pbuffer++;
 927                        *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
 928                        DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
 929                        pbuffer++;
 930                }
 931                if (size & 0x0001) {
 932                        //copy odd byte from fifo
 933                        tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
 934                        *pbuffer = ntohs(tempword);
 935                }
 936                spin_unlock_irqrestore(&info->dpram_lock, flags);
 937
 938                // Check if pseudo header checksum is good
 939                // Calculate pseudo header checksum
 940                tempword = *ppseudohdr++;
 941                for (i = 1; i < 7; i++) {
 942                        tempword ^= *ppseudohdr++;
 943                }
 944                if ((tempword != *ppseudohdr)) {
 945                        DEBUG(1,
 946                                  "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n");
 947                        // Drop this message
 948                        return false;
 949                }
 950                return true;
 951        }
 952}
 953
 954//---------------------------------------------------------------------------
 955//
 956// Function:   ft1000_proc_drvmsg
 957// Description: This function will process the various driver messages.
 958// Input:
 959//     dev    - device structure
 960//     pnxtph - pointer to next pseudo header
 961// Output:
 962//     none
 963//
 964//---------------------------------------------------------------------------
 965static void ft1000_proc_drvmsg(struct net_device *dev)
 966{
 967        struct ft1000_info *info = netdev_priv(dev);
 968        u16 msgtype;
 969        u16 tempword;
 970        struct media_msg *pmediamsg;
 971        struct dsp_init_msg *pdspinitmsg;
 972        struct drv_msg *pdrvmsg;
 973        u16 len;
 974        u16 i;
 975        struct prov_record *ptr;
 976        struct pseudo_hdr *ppseudo_hdr;
 977        u16 *pmsg;
 978        struct timeval tv;
 979        union {
 980                u8 byte[2];
 981                u16 wrd;
 982        } convert;
 983
 984    if (info->AsicID == ELECTRABUZZ_ID) {
 985        tempword = FT1000_DPRAM_RX_BASE+2;
 986    }
 987    else {
 988        tempword = FT1000_DPRAM_MAG_RX_BASE;
 989    }
 990    if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) {
 991
 992                // Get the message type which is total_len + PSEUDO header + msgtype + message body
 993                pdrvmsg = (struct drv_msg *) & cmdbuffer[0];
 994                msgtype = ntohs(pdrvmsg->type);
 995                DEBUG(1, "Command message type = 0x%x\n", msgtype);
 996                switch (msgtype) {
 997                case DSP_PROVISION:
 998                        DEBUG(0,
 999                                  "Got a provisioning request message from DSP\n");
1000                        mdelay(25);
1001                        while (list_empty(&info->prov_list) == 0) {
1002                                DEBUG(0, "Sending a provisioning message\n");
1003                                // Make sure SLOWQ doorbell is clear
1004                                tempword =
1005                                        ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1006                                i = 0;
1007                                while (tempword & FT1000_DB_DPRAM_TX) {
1008                                        mdelay(5);
1009                                        i++;
1010                                        if (i == 10) {
1011                                                break;
1012                                        }
1013                                }
1014                                ptr =
1015                                        list_entry(info->prov_list.next,
1016                                                   struct prov_record, list);
1017                                len = *(u16 *) ptr->pprov_data;
1018                                len = htons(len);
1019
1020                                pmsg = (u16 *) ptr->pprov_data;
1021                                ppseudo_hdr = (struct pseudo_hdr *) pmsg;
1022                                // Insert slow queue sequence number
1023                                ppseudo_hdr->seq_num = info->squeseqnum++;
1024                                ppseudo_hdr->portsrc = 0;
1025                                // Calculate new checksum
1026                                ppseudo_hdr->checksum = *pmsg++;
1027                                DEBUG(1, "checksum = 0x%x\n",
1028                                          ppseudo_hdr->checksum);
1029                                for (i = 1; i < 7; i++) {
1030                                        ppseudo_hdr->checksum ^= *pmsg++;
1031                                        DEBUG(1, "checksum = 0x%x\n",
1032                                                  ppseudo_hdr->checksum);
1033                                }
1034
1035                                ft1000_send_cmd (dev, (u16 *)ptr->pprov_data, len, SLOWQ_TYPE);
1036                                list_del(&ptr->list);
1037                                kfree(ptr->pprov_data);
1038                                kfree(ptr);
1039                        }
1040                        // Indicate adapter is ready to take application messages after all
1041                        // provisioning messages are sent
1042                        info->CardReady = 1;
1043                        break;
1044                case MEDIA_STATE:
1045                        pmediamsg = (struct media_msg *) & cmdbuffer[0];
1046                        if (info->ProgConStat != 0xFF) {
1047                        if (pmediamsg->state) {
1048                                DEBUG(1, "Media is up\n");
1049                                if (info->mediastate == 0) {
1050                                        netif_carrier_on(dev);
1051                                        netif_wake_queue(dev);
1052                                        info->mediastate = 1;
1053                                        do_gettimeofday(&tv);
1054                                        info->ConTm = tv.tv_sec;
1055                                }
1056                        } else {
1057                                DEBUG(1, "Media is down\n");
1058                                if (info->mediastate == 1) {
1059                                        info->mediastate = 0;
1060                                        netif_carrier_off(dev);
1061                                        netif_stop_queue(dev);
1062                                        info->ConTm = 0;
1063                                }
1064                        }
1065            }
1066            else {
1067                DEBUG(1,"Media is down\n");
1068                if (info->mediastate == 1) {
1069                    info->mediastate = 0;
1070                    netif_carrier_off(dev);
1071                    netif_stop_queue(dev);
1072                    info->ConTm = 0;
1073                }
1074            }
1075                        break;
1076                case DSP_INIT_MSG:
1077                        pdspinitmsg = (struct dsp_init_msg *) & cmdbuffer[0];
1078                        memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
1079                        DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
1080                                  info->DspVer[0], info->DspVer[1], info->DspVer[2],
1081                                   info->DspVer[3]);
1082                        memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
1083                                   HWSERNUMSZ);
1084                        memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
1085                        memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
1086                        dev->dev_addr[0] = info->eui64[0];
1087                        dev->dev_addr[1] = info->eui64[1];
1088                        dev->dev_addr[2] = info->eui64[2];
1089                        dev->dev_addr[3] = info->eui64[5];
1090                        dev->dev_addr[4] = info->eui64[6];
1091                        dev->dev_addr[5] = info->eui64[7];
1092
1093                        if (ntohs(pdspinitmsg->length) ==
1094                                (sizeof(struct dsp_init_msg) - 20)) {
1095                                memcpy(info->ProductMode,
1096                                           pdspinitmsg->ProductMode, MODESZ);
1097                                memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
1098                                           CALVERSZ);
1099                                memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
1100                                           CALDATESZ);
1101                                DEBUG(1, "RFCalVer = 0x%2x 0x%2x\n",
1102                                          info->RfCalVer[0], info->RfCalVer[1]);
1103                        }
1104
1105                        break ;
1106                case DSP_STORE_INFO:
1107                        DEBUG(1, "FT1000:drivermsg:Got DSP_STORE_INFO\n");
1108                        tempword = ntohs(pdrvmsg->length);
1109                        info->DSPInfoBlklen = tempword;
1110                        if (tempword < (MAX_DSP_SESS_REC - 4)) {
1111                                pmsg = (u16 *) & pdrvmsg->data[0];
1112                                for (i = 0; i < ((tempword + 1) / 2); i++) {
1113                                        DEBUG(1,
1114                                                  "FT1000:drivermsg:dsp info data = 0x%x\n",
1115                                                  *pmsg);
1116                                        info->DSPInfoBlk[i + 10] = *pmsg++;
1117                                }
1118                        }
1119                        break;
1120                case DSP_GET_INFO:
1121                        DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n");
1122                        // copy dsp info block to dsp
1123                        // allow any outstanding ioctl to finish
1124                        mdelay(10);
1125                        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1126                        if (tempword & FT1000_DB_DPRAM_TX) {
1127                                mdelay(10);
1128                                tempword =
1129                                        ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1130                                if (tempword & FT1000_DB_DPRAM_TX) {
1131                                        mdelay(10);
1132                                }
1133                        }
1134
1135                        if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1136                                // Put message into Slow Queue
1137                                // Form Pseudo header
1138                                pmsg = (u16 *) info->DSPInfoBlk;
1139                                ppseudo_hdr = (struct pseudo_hdr *) pmsg;
1140                                ppseudo_hdr->length =
1141                                        htons(info->DSPInfoBlklen + 4);
1142                                ppseudo_hdr->source = 0x10;
1143                                ppseudo_hdr->destination = 0x20;
1144                                ppseudo_hdr->portdest = 0;
1145                                ppseudo_hdr->portsrc = 0;
1146                                ppseudo_hdr->sh_str_id = 0;
1147                                ppseudo_hdr->control = 0;
1148                                ppseudo_hdr->rsvd1 = 0;
1149                                ppseudo_hdr->rsvd2 = 0;
1150                                ppseudo_hdr->qos_class = 0;
1151                                // Insert slow queue sequence number
1152                                ppseudo_hdr->seq_num = info->squeseqnum++;
1153                                // Insert application id
1154                                ppseudo_hdr->portsrc = 0;
1155                                // Calculate new checksum
1156                                ppseudo_hdr->checksum = *pmsg++;
1157                                for (i = 1; i < 7; i++) {
1158                                        ppseudo_hdr->checksum ^= *pmsg++;
1159                                }
1160                                info->DSPInfoBlk[8] = 0x7200;
1161                                info->DSPInfoBlk[9] =
1162                                        htons(info->DSPInfoBlklen);
1163                                ft1000_send_cmd (dev, (u16 *)info->DSPInfoBlk, (u16)(info->DSPInfoBlklen+4), 0);
1164                        }
1165
1166                        break;
1167                case GET_DRV_ERR_RPT_MSG:
1168                        DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
1169                        // copy driver error message to dsp
1170                        // allow any outstanding ioctl to finish
1171                        mdelay(10);
1172                        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1173                        if (tempword & FT1000_DB_DPRAM_TX) {
1174                                mdelay(10);
1175                                tempword =
1176                                        ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1177                                if (tempword & FT1000_DB_DPRAM_TX) {
1178                                        mdelay(10);
1179                                }
1180                        }
1181
1182                        if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1183                                // Put message into Slow Queue
1184                                // Form Pseudo header
1185                                pmsg = (u16 *) & tempbuffer[0];
1186                                ppseudo_hdr = (struct pseudo_hdr *) pmsg;
1187                                ppseudo_hdr->length = htons(0x0012);
1188                                ppseudo_hdr->source = 0x10;
1189                                ppseudo_hdr->destination = 0x20;
1190                                ppseudo_hdr->portdest = 0;
1191                                ppseudo_hdr->portsrc = 0;
1192                                ppseudo_hdr->sh_str_id = 0;
1193                                ppseudo_hdr->control = 0;
1194                                ppseudo_hdr->rsvd1 = 0;
1195                                ppseudo_hdr->rsvd2 = 0;
1196                                ppseudo_hdr->qos_class = 0;
1197                                // Insert slow queue sequence number
1198                                ppseudo_hdr->seq_num = info->squeseqnum++;
1199                                // Insert application id
1200                                ppseudo_hdr->portsrc = 0;
1201                                // Calculate new checksum
1202                ppseudo_hdr->checksum = *pmsg++;
1203                for (i=1; i<7; i++) {
1204                    ppseudo_hdr->checksum ^= *pmsg++;
1205                }
1206                                pmsg = (u16 *) & tempbuffer[16];
1207                                *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
1208                                *pmsg++ = htons(0x000e);
1209                                *pmsg++ = htons(info->DSP_TIME[0]);
1210                                *pmsg++ = htons(info->DSP_TIME[1]);
1211                                *pmsg++ = htons(info->DSP_TIME[2]);
1212                                *pmsg++ = htons(info->DSP_TIME[3]);
1213                                convert.byte[0] = info->DspVer[0];
1214                                convert.byte[1] = info->DspVer[1];
1215                                *pmsg++ = convert.wrd;
1216                                convert.byte[0] = info->DspVer[2];
1217                                convert.byte[1] = info->DspVer[3];
1218                                *pmsg++ = convert.wrd;
1219                                *pmsg++ = htons(info->DrvErrNum);
1220
1221                                ft1000_send_cmd (dev, (u16 *)&tempbuffer[0], (u16)(0x0012), 0);
1222                                info->DrvErrNum = 0;
1223                        }
1224
1225                        break;
1226                default:
1227                        break;
1228                }
1229        }
1230}
1231
1232//---------------------------------------------------------------------------
1233//
1234// Function:   ft1000_parse_dpram_msg
1235// Description: This function will parse the message received from the DSP
1236//             via the DPRAM interface.
1237// Input:
1238//     dev    - device structure
1239// Output:
1240//     status - FAILURE
1241//              SUCCESS
1242//
1243//---------------------------------------------------------------------------
1244static int ft1000_parse_dpram_msg(struct net_device *dev)
1245{
1246        struct ft1000_info *info = netdev_priv(dev);
1247        u16 doorbell;
1248        u16 portid;
1249        u16 nxtph;
1250        u16 total_len;
1251        int i = 0;
1252        int cnt;
1253        unsigned long flags;
1254
1255        doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1256        DEBUG(1, "Doorbell = 0x%x\n", doorbell);
1257
1258        if (doorbell & FT1000_ASIC_RESET_REQ) {
1259                // Copy DSP session record from info block
1260                spin_lock_irqsave(&info->dpram_lock, flags);
1261                if (info->AsicID == ELECTRABUZZ_ID) {
1262                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1263                                         FT1000_DPRAM_RX_BASE);
1264                        for (i = 0; i < MAX_DSP_SESS_REC; i++) {
1265                                ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA,
1266                                                 info->DSPSess.Rec[i]);
1267                        }
1268                } else {
1269                        ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1270                                         FT1000_DPRAM_MAG_RX_BASE);
1271                        for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
1272                                outl(info->DSPSess.MagRec[i],
1273                                         dev->base_addr + FT1000_REG_MAG_DPDATA);
1274                        }
1275                }
1276                spin_unlock_irqrestore(&info->dpram_lock, flags);
1277
1278                // clear ASIC RESET request
1279                ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1280                                 FT1000_ASIC_RESET_REQ);
1281                DEBUG(1, "Got an ASIC RESET Request\n");
1282                ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1283                                 FT1000_ASIC_RESET_DSP);
1284
1285                if (info->AsicID == MAGNEMITE_ID) {
1286                        // Setting MAGNEMITE ASIC to big endian mode
1287                        ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
1288                                         HOST_INTF_BE);
1289                }
1290        }
1291
1292        if (doorbell & FT1000_DSP_ASIC_RESET) {
1293                DEBUG(0,
1294                          "FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n");
1295                ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1296                                 FT1000_DSP_ASIC_RESET);
1297                udelay(200);
1298                return SUCCESS;
1299        }
1300
1301        if (doorbell & FT1000_DB_DPRAM_RX) {
1302                DEBUG(1,
1303                          "FT1000:ft1000_parse_dpram_msg: Got a slow queue message\n");
1304                nxtph = FT1000_DPRAM_RX_BASE + 2;
1305                if (info->AsicID == ELECTRABUZZ_ID) {
1306                        total_len =
1307                                ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE);
1308                } else {
1309                        total_len =
1310                                ntohs(ft1000_read_dpram_mag_16
1311                                  (dev, FT1000_MAG_TOTAL_LEN,
1312                                   FT1000_MAG_TOTAL_LEN_INDX));
1313                }
1314                DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n",
1315                          total_len);
1316                if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) {
1317            total_len += nxtph;
1318            cnt = 0;
1319            // ft1000_read_reg will return a value that needs to be byteswap
1320            // in order to get DSP_QID_OFFSET.
1321                        if (info->AsicID == ELECTRABUZZ_ID) {
1322                                portid =
1323                                        (ft1000_read_dpram
1324                                         (dev,
1325                                          DSP_QID_OFFSET + FT1000_DPRAM_RX_BASE +
1326                                          2) >> 8) & 0xff;
1327                        } else {
1328                                portid =
1329                                        (ft1000_read_dpram_mag_16
1330                                         (dev, FT1000_MAG_PORT_ID,
1331                                          FT1000_MAG_PORT_ID_INDX) & 0xff);
1332                        }
1333                        DEBUG(1, "DSP_QID = 0x%x\n", portid);
1334
1335                        if (portid == DRIVERID) {
1336                                // We are assumming one driver message from the DSP at a time.
1337                                ft1000_proc_drvmsg(dev);
1338                        }
1339                }
1340                ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX);
1341        }
1342
1343        if (doorbell & FT1000_DB_COND_RESET) {
1344                // Reset ASIC and DSP
1345                if (info->AsicID == ELECTRABUZZ_ID) {
1346                        info->DSP_TIME[0] =
1347                                ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1348                        info->DSP_TIME[1] =
1349                                ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1350                        info->DSP_TIME[2] =
1351                                ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1352                        info->DSP_TIME[3] =
1353                                ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1354                } else {
1355                        info->DSP_TIME[0] =
1356                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1357                                                         FT1000_MAG_DSP_TIMER0_INDX);
1358                        info->DSP_TIME[1] =
1359                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1360                                                         FT1000_MAG_DSP_TIMER1_INDX);
1361                        info->DSP_TIME[2] =
1362                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1363                                                         FT1000_MAG_DSP_TIMER2_INDX);
1364                        info->DSP_TIME[3] =
1365                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1366                                                         FT1000_MAG_DSP_TIMER3_INDX);
1367                }
1368                info->DrvErrNum = DSP_CONDRESET_INFO;
1369                DEBUG(1, "ft1000_hw:DSP conditional reset requested\n");
1370                ft1000_reset_card(dev);
1371                ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1372                                 FT1000_DB_COND_RESET);
1373        }
1374        // let's clear any unexpected doorbells from DSP
1375        doorbell =
1376                doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ |
1377                         FT1000_DB_COND_RESET | 0xff00);
1378        if (doorbell) {
1379                DEBUG(1, "Clearing unexpected doorbell = 0x%x\n", doorbell);
1380                ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell);
1381        }
1382
1383        return SUCCESS;
1384
1385}
1386
1387//---------------------------------------------------------------------------
1388//
1389// Function:   ft1000_flush_fifo
1390// Description: This function will flush one packet from the downlink
1391//             FIFO.
1392// Input:
1393//     dev      - device structure
1394//     drv_err  - driver error causing the flush fifo
1395// Output:
1396//     None.
1397//
1398//---------------------------------------------------------------------------
1399static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
1400{
1401        struct ft1000_info *info = netdev_priv(dev);
1402        u16 i;
1403        u32 templong;
1404        u16 tempword;
1405
1406        DEBUG(1, "ft1000:ft1000_hw:ft1000_flush_fifo called\n");
1407        if (info->PktIntfErr > MAX_PH_ERR) {
1408                if (info->AsicID == ELECTRABUZZ_ID) {
1409                        info->DSP_TIME[0] =
1410                                ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1411                        info->DSP_TIME[1] =
1412                                ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1413                        info->DSP_TIME[2] =
1414                                ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1415                        info->DSP_TIME[3] =
1416                                ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1417                } else {
1418                        info->DSP_TIME[0] =
1419                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1420                                                         FT1000_MAG_DSP_TIMER0_INDX);
1421                        info->DSP_TIME[1] =
1422                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1423                                                         FT1000_MAG_DSP_TIMER1_INDX);
1424                        info->DSP_TIME[2] =
1425                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1426                                                         FT1000_MAG_DSP_TIMER2_INDX);
1427                        info->DSP_TIME[3] =
1428                                ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1429                                                         FT1000_MAG_DSP_TIMER3_INDX);
1430                }
1431                info->DrvErrNum = DrvErrNum;
1432                ft1000_reset_card(dev);
1433                return;
1434        } else {
1435                // Flush corrupted pkt from FIFO
1436                i = 0;
1437                do {
1438                        if (info->AsicID == ELECTRABUZZ_ID) {
1439                                tempword =
1440                                        ft1000_read_reg(dev, FT1000_REG_DFIFO);
1441                                tempword =
1442                                        ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
1443                        } else {
1444                                templong =
1445                                        inl(dev->base_addr + FT1000_REG_MAG_DFR);
1446                                tempword =
1447                                        inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1448                        }
1449                        i++;
1450                        // This should never happen unless the ASIC is broken.
1451                        // We must reset to recover.
1452                        if ((i > 2048) || (tempword == 0)) {
1453                                if (info->AsicID == ELECTRABUZZ_ID) {
1454                                        info->DSP_TIME[0] =
1455                                                ft1000_read_dpram(dev,
1456                                                                  FT1000_DSP_TIMER0);
1457                                        info->DSP_TIME[1] =
1458                                                ft1000_read_dpram(dev,
1459                                                                  FT1000_DSP_TIMER1);
1460                                        info->DSP_TIME[2] =
1461                                                ft1000_read_dpram(dev,
1462                                                                  FT1000_DSP_TIMER2);
1463                                        info->DSP_TIME[3] =
1464                                                ft1000_read_dpram(dev,
1465                                                                  FT1000_DSP_TIMER3);
1466                                } else {
1467                                        info->DSP_TIME[0] =
1468                                                ft1000_read_dpram_mag_16(dev,
1469                                                                         FT1000_MAG_DSP_TIMER0,
1470                                                                         FT1000_MAG_DSP_TIMER0_INDX);
1471                                        info->DSP_TIME[1] =
1472                                                ft1000_read_dpram_mag_16(dev,
1473                                                                         FT1000_MAG_DSP_TIMER1,
1474                                                                         FT1000_MAG_DSP_TIMER1_INDX);
1475                                        info->DSP_TIME[2] =
1476                                                ft1000_read_dpram_mag_16(dev,
1477                                                                         FT1000_MAG_DSP_TIMER2,
1478                                                                         FT1000_MAG_DSP_TIMER2_INDX);
1479                                        info->DSP_TIME[3] =
1480                                                ft1000_read_dpram_mag_16(dev,
1481                                                                         FT1000_MAG_DSP_TIMER3,
1482                                                                         FT1000_MAG_DSP_TIMER3_INDX);
1483                                }
1484                                if (tempword == 0) {
1485                                        // Let's check if ASIC reads are still ok by reading the Mask register
1486                                        // which is never zero at this point of the code.
1487                                        tempword =
1488                                                inw(dev->base_addr +
1489                                                FT1000_REG_SUP_IMASK);
1490                                        if (tempword == 0) {
1491                                                // This indicates that we can not communicate with the ASIC
1492                                                info->DrvErrNum =
1493                                                        FIFO_FLUSH_BADCNT;
1494                                        } else {
1495                                                // Let's assume that we really flush the FIFO
1496                                                info->PktIntfErr++;
1497                                                return;
1498                                        }
1499                                } else {
1500                                        info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
1501                                }
1502                                return;
1503                        }
1504                        tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1505                } while ((tempword & 0x03) != 0x03);
1506                if (info->AsicID == ELECTRABUZZ_ID) {
1507                        i++;
1508                        DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1509                        // Flush last word in FIFO.
1510                        tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1511                        // Update FIFO counter for DSP
1512                        i = i * 2;
1513                        DEBUG(0, "Flush Data byte count to dsp = %d\n", i);
1514                        info->fifo_cnt += i;
1515                        ft1000_write_dpram(dev, FT1000_FIFO_LEN,
1516                                           info->fifo_cnt);
1517                } else {
1518                        DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1519                        // Flush last word in FIFO
1520                        templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1521                        tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1522                        DEBUG(0, "FT1000_REG_SUP_STAT = 0x%x\n", tempword);
1523                        tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1524                        DEBUG(0, "FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
1525                }
1526                if (DrvErrNum) {
1527                        info->PktIntfErr++;
1528                }
1529        }
1530}
1531
1532//---------------------------------------------------------------------------
1533//
1534// Function:   ft1000_copy_up_pkt
1535// Description: This function will pull Flarion packets out of the Downlink
1536//             FIFO and convert it to an ethernet packet.  The ethernet packet will
1537//             then be deliver to the TCP/IP stack.
1538// Input:
1539//     dev    - device structure
1540// Output:
1541//     status - FAILURE
1542//              SUCCESS
1543//
1544//---------------------------------------------------------------------------
1545static int ft1000_copy_up_pkt(struct net_device *dev)
1546{
1547        u16 tempword;
1548        struct ft1000_info *info = netdev_priv(dev);
1549        u16 len;
1550        struct sk_buff *skb;
1551        u16 i;
1552        u8 *pbuffer = NULL;
1553        u8 *ptemp = NULL;
1554        u16 chksum;
1555        u32 *ptemplong;
1556        u32 templong;
1557
1558        DEBUG(1, "ft1000_copy_up_pkt\n");
1559        // Read length
1560        if (info->AsicID == ELECTRABUZZ_ID) {
1561                tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1562                len = tempword;
1563        } else {
1564                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1565                len = ntohs(tempword);
1566        }
1567        chksum = tempword;
1568        DEBUG(1, "Number of Bytes in FIFO = %d\n", len);
1569
1570        if (len > ENET_MAX_SIZE) {
1571                DEBUG(0, "size of ethernet packet invalid\n");
1572                if (info->AsicID == MAGNEMITE_ID) {
1573                        // Read High word to complete 32 bit access
1574                        tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1575                }
1576                ft1000_flush_fifo(dev, DSP_PKTLEN_INFO);
1577                info->stats.rx_errors++;
1578                return FAILURE;
1579        }
1580
1581        skb = dev_alloc_skb(len + 12 + 2);
1582
1583        if (skb == NULL) {
1584                DEBUG(0, "No Network buffers available\n");
1585                // Read High word to complete 32 bit access
1586                if (info->AsicID == MAGNEMITE_ID) {
1587                        tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1588                }
1589                ft1000_flush_fifo(dev, 0);
1590                info->stats.rx_errors++;
1591                return FAILURE;
1592        }
1593        pbuffer = (u8 *) skb_put(skb, len + 12);
1594
1595        // Pseudo header
1596        if (info->AsicID == ELECTRABUZZ_ID) {
1597                for (i = 1; i < 7; i++) {
1598                        tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1599                        chksum ^= tempword;
1600                }
1601                // read checksum value
1602                tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1603        } else {
1604                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1605                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1606                chksum ^= tempword;
1607
1608                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1609                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1610                chksum ^= tempword;
1611
1612                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1613                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1614                chksum ^= tempword;
1615
1616                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1617                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1618                chksum ^= tempword;
1619
1620                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1621                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1622                chksum ^= tempword;
1623
1624                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1625                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1626                chksum ^= tempword;
1627
1628                // read checksum value
1629                tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1630                DEBUG(1, "Pseudo = 0x%x\n", tempword);
1631        }
1632
1633        if (chksum != tempword) {
1634                DEBUG(0, "Packet checksum mismatch 0x%x 0x%x\n", chksum,
1635                          tempword);
1636                ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO);
1637                info->stats.rx_errors++;
1638                kfree_skb(skb);
1639                return FAILURE;
1640        }
1641        //subtract the number of bytes read already
1642        ptemp = pbuffer;
1643
1644        // fake MAC address
1645        *pbuffer++ = dev->dev_addr[0];
1646        *pbuffer++ = dev->dev_addr[1];
1647        *pbuffer++ = dev->dev_addr[2];
1648        *pbuffer++ = dev->dev_addr[3];
1649        *pbuffer++ = dev->dev_addr[4];
1650        *pbuffer++ = dev->dev_addr[5];
1651        *pbuffer++ = 0x00;
1652        *pbuffer++ = 0x07;
1653        *pbuffer++ = 0x35;
1654        *pbuffer++ = 0xff;
1655        *pbuffer++ = 0xff;
1656        *pbuffer++ = 0xfe;
1657
1658        if (info->AsicID == ELECTRABUZZ_ID) {
1659                for (i = 0; i < len / 2; i++) {
1660                        tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1661                        *pbuffer++ = (u8) (tempword >> 8);
1662                        *pbuffer++ = (u8) tempword;
1663                        if (ft1000_chkcard(dev) == false) {
1664                                kfree_skb(skb);
1665                                return FAILURE;
1666                        }
1667                }
1668
1669                // Need to read one more word if odd byte
1670                if (len & 0x0001) {
1671                        tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1672                        *pbuffer++ = (u8) (tempword >> 8);
1673                }
1674        } else {
1675                ptemplong = (u32 *) pbuffer;
1676                for (i = 0; i < len / 4; i++) {
1677                        templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1678                        DEBUG(1, "Data = 0x%8x\n", templong);
1679                        *ptemplong++ = templong;
1680                }
1681
1682                // Need to read one more word if odd align.
1683                if (len & 0x0003) {
1684                        templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1685                        DEBUG(1, "Data = 0x%8x\n", templong);
1686                        *ptemplong++ = templong;
1687                }
1688
1689        }
1690
1691        DEBUG(1, "Data passed to Protocol layer:\n");
1692        for (i = 0; i < len + 12; i++) {
1693                DEBUG(1, "Protocol Data: 0x%x\n ", *ptemp++);
1694        }
1695
1696        skb->dev = dev;
1697        skb->protocol = eth_type_trans(skb, dev);
1698        skb->ip_summed = CHECKSUM_UNNECESSARY;
1699        netif_rx(skb);
1700
1701        info->stats.rx_packets++;
1702        // Add on 12 bytes for MAC address which was removed
1703        info->stats.rx_bytes += (len + 12);
1704
1705        if (info->AsicID == ELECTRABUZZ_ID) {
1706                // track how many bytes have been read from FIFO - round up to 16 bit word
1707                tempword = len + 16;
1708                if (tempword & 0x01)
1709                        tempword++;
1710                info->fifo_cnt += tempword;
1711                ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN);
1712                ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt);
1713        }
1714
1715        return SUCCESS;
1716}
1717
1718//---------------------------------------------------------------------------
1719//
1720// Function:   ft1000_copy_down_pkt
1721// Description: This function will take an ethernet packet and convert it to
1722//             a Flarion packet prior to sending it to the ASIC Downlink
1723//             FIFO.
1724// Input:
1725//     dev    - device structure
1726//     packet - address of ethernet packet
1727//     len    - length of IP packet
1728// Output:
1729//     status - FAILURE
1730//              SUCCESS
1731//
1732//---------------------------------------------------------------------------
1733static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
1734{
1735        struct ft1000_info *info = netdev_priv(dev);
1736        union {
1737                struct pseudo_hdr blk;
1738                u16 buff[sizeof(struct pseudo_hdr) >> 1];
1739                u8 buffc[sizeof(struct pseudo_hdr)];
1740        } pseudo;
1741        int i;
1742        u32 *plong;
1743
1744        DEBUG(1, "ft1000_hw: copy_down_pkt()\n");
1745
1746        // Check if there is room on the FIFO
1747        if (len > ft1000_read_fifo_len(dev)) {
1748                udelay(10);
1749                if (len > ft1000_read_fifo_len(dev)) {
1750                        udelay(20);
1751                }
1752                if (len > ft1000_read_fifo_len(dev)) {
1753                        udelay(20);
1754                }
1755                if (len > ft1000_read_fifo_len(dev)) {
1756                        udelay(20);
1757                }
1758                if (len > ft1000_read_fifo_len(dev)) {
1759                        udelay(20);
1760                }
1761                if (len > ft1000_read_fifo_len(dev)) {
1762                        udelay(20);
1763                }
1764                if (len > ft1000_read_fifo_len(dev)) {
1765                        DEBUG(1,
1766                                  "ft1000_hw:ft1000_copy_down_pkt:Transmit FIFO is fulli - pkt drop\n");
1767                        info->stats.tx_errors++;
1768                        return SUCCESS;
1769                }
1770        }
1771        // Create pseudo header and send pseudo/ip to hardware
1772        if (info->AsicID == ELECTRABUZZ_ID) {
1773                pseudo.blk.length = len;
1774        } else {
1775                pseudo.blk.length = ntohs(len);
1776        }
1777        pseudo.blk.source = DSPID;      // Need to swap to get in correct order
1778        pseudo.blk.destination = HOSTID;
1779        pseudo.blk.portdest = NETWORKID;        // Need to swap to get in correct order
1780        pseudo.blk.portsrc = DSPAIRID;
1781        pseudo.blk.sh_str_id = 0;
1782        pseudo.blk.control = 0;
1783        pseudo.blk.rsvd1 = 0;
1784        pseudo.blk.seq_num = 0;
1785        pseudo.blk.rsvd2 = info->packetseqnum++;
1786        pseudo.blk.qos_class = 0;
1787        /* Calculate pseudo header checksum */
1788        pseudo.blk.checksum = pseudo.buff[0];
1789        for (i = 1; i < 7; i++) {
1790                pseudo.blk.checksum ^= pseudo.buff[i];
1791        }
1792
1793        // Production Mode
1794        if (info->AsicID == ELECTRABUZZ_ID) {
1795                // copy first word to UFIFO_BEG reg
1796                ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]);
1797                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 0 BEG = 0x%04x\n",
1798                          pseudo.buff[0]);
1799
1800                // copy subsequent words to UFIFO_MID reg
1801                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]);
1802                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 1 MID = 0x%04x\n",
1803                          pseudo.buff[1]);
1804                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]);
1805                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 2 MID = 0x%04x\n",
1806                          pseudo.buff[2]);
1807                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]);
1808                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 3 MID = 0x%04x\n",
1809                          pseudo.buff[3]);
1810                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]);
1811                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 4 MID = 0x%04x\n",
1812                          pseudo.buff[4]);
1813                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]);
1814                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 5 MID = 0x%04x\n",
1815                          pseudo.buff[5]);
1816                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]);
1817                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 6 MID = 0x%04x\n",
1818                          pseudo.buff[6]);
1819                ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]);
1820                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 7 MID = 0x%04x\n",
1821                          pseudo.buff[7]);
1822
1823                // Write PPP type + IP Packet into Downlink FIFO
1824                for (i = 0; i < (len >> 1) - 1; i++) {
1825                        ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1826                                         htons(*packet));
1827                        DEBUG(1,
1828                                  "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1829                                  i + 8, htons(*packet));
1830                        packet++;
1831                }
1832
1833                // Check for odd byte
1834                if (len & 0x0001) {
1835                        ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1836                                         htons(*packet));
1837                        DEBUG(1,
1838                                  "ft1000_hw:ft1000_copy_down_pkt:data MID = 0x%04x\n",
1839                                  htons(*packet));
1840                        packet++;
1841                        ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1842                                         htons(*packet));
1843                        DEBUG(1,
1844                                  "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1845                                  i + 8, htons(*packet));
1846                } else {
1847                        ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1848                                         htons(*packet));
1849                        DEBUG(1,
1850                                  "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1851                                  i + 8, htons(*packet));
1852                }
1853        } else {
1854                outl(*(u32 *) & pseudo.buff[0],
1855                         dev->base_addr + FT1000_REG_MAG_UFDR);
1856                DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1857                          *(u32 *) & pseudo.buff[0]);
1858                outl(*(u32 *) & pseudo.buff[2],
1859                         dev->base_addr + FT1000_REG_MAG_UFDR);
1860                DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1861                          *(u32 *) & pseudo.buff[2]);
1862                outl(*(u32 *) & pseudo.buff[4],
1863                         dev->base_addr + FT1000_REG_MAG_UFDR);
1864                DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1865                          *(u32 *) & pseudo.buff[4]);
1866                outl(*(u32 *) & pseudo.buff[6],
1867                         dev->base_addr + FT1000_REG_MAG_UFDR);
1868                DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1869                          *(u32 *) & pseudo.buff[6]);
1870
1871                plong = (u32 *) packet;
1872                // Write PPP type + IP Packet into Downlink FIFO
1873                for (i = 0; i < (len >> 2); i++) {
1874                        outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1875                }
1876
1877                // Check for odd alignment
1878                if (len & 0x0003) {
1879                        DEBUG(1,
1880                                  "ft1000_hw:ft1000_copy_down_pkt:data = 0x%8x\n",
1881                                  *plong);
1882                        outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1883                }
1884                outl(1, dev->base_addr + FT1000_REG_MAG_UFER);
1885        }
1886
1887        info->stats.tx_packets++;
1888        // Add 14 bytes for MAC address plus ethernet type
1889        info->stats.tx_bytes += (len + 14);
1890        return SUCCESS;
1891}
1892
1893static struct net_device_stats *ft1000_stats(struct net_device *dev)
1894{
1895        struct ft1000_info *info = netdev_priv(dev);
1896        return (&info->stats);
1897}
1898
1899static int ft1000_open(struct net_device *dev)
1900{
1901
1902        DEBUG(0, "ft1000_hw: ft1000_open is called\n");
1903
1904        ft1000_reset_card(dev);
1905        DEBUG(0, "ft1000_hw: ft1000_open is ended\n");
1906
1907        /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP and ASIC */
1908        init_timer(&poll_timer);
1909        poll_timer.expires = jiffies + (2 * HZ);
1910        poll_timer.data = (u_long) dev;
1911        add_timer(&poll_timer);
1912
1913        DEBUG(0, "ft1000_hw: ft1000_open is ended2\n");
1914        return 0;
1915}
1916
1917static int ft1000_close(struct net_device *dev)
1918{
1919        struct ft1000_info *info = netdev_priv(dev);
1920
1921        DEBUG(0, "ft1000_hw: ft1000_close()\n");
1922
1923        info->CardReady = 0;
1924        del_timer(&poll_timer);
1925
1926        if (ft1000_card_present == 1) {
1927                DEBUG(0, "Media is down\n");
1928                netif_stop_queue(dev);
1929
1930                ft1000_disable_interrupts(dev);
1931                ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
1932
1933                //reset ASIC
1934                ft1000_reset_asic(dev);
1935        }
1936        return 0;
1937}
1938
1939static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
1940{
1941        struct ft1000_info *info = netdev_priv(dev);
1942        u8 *pdata;
1943
1944        DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n");
1945        if (skb == NULL) {
1946                DEBUG(1, "ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n");
1947                return 0;
1948        }
1949
1950        DEBUG(1, "ft1000_hw: ft1000_start_xmit:length of packet = %d\n",
1951                  skb->len);
1952
1953        pdata = (u8 *) skb->data;
1954
1955        if (info->mediastate == 0) {
1956                /* Drop packet is mediastate is down */
1957                DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:mediastate is down\n");
1958                return SUCCESS;
1959        }
1960
1961        if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
1962                /* Drop packet which has invalid size */
1963                DEBUG(1,
1964                          "ft1000_hw:ft1000_copy_down_pkt:invalid ethernet length\n");
1965                return SUCCESS;
1966        }
1967        ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2),
1968                                 skb->len - ENET_HEADER_SIZE + 2);
1969
1970        dev_kfree_skb(skb);
1971
1972        return 0;
1973}
1974
1975static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
1976{
1977        struct net_device *dev = (struct net_device *)dev_id;
1978        struct ft1000_info *info = netdev_priv(dev);
1979        u16 tempword;
1980        u16 inttype;
1981        int cnt;
1982
1983        DEBUG(1, "ft1000_hw: ft1000_interrupt()\n");
1984
1985        if (info->CardReady == 0) {
1986                ft1000_disable_interrupts(dev);
1987                return IRQ_HANDLED;
1988        }
1989
1990        if (ft1000_chkcard(dev) == false) {
1991                ft1000_disable_interrupts(dev);
1992                return IRQ_HANDLED;
1993        }
1994
1995        ft1000_disable_interrupts(dev);
1996
1997        // Read interrupt type
1998        inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
1999
2000    // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type
2001    while (inttype) {
2002        if (inttype & ISR_DOORBELL_PEND) {
2003                ft1000_parse_dpram_msg(dev);
2004        }
2005
2006        if (inttype & ISR_RCV) {
2007                DEBUG(1, "Data in FIFO\n");
2008
2009                cnt = 0;
2010                do {
2011                        // Check if we have packets in the Downlink FIFO
2012                        if (info->AsicID == ELECTRABUZZ_ID) {
2013                                tempword =
2014                                        ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
2015                        } else {
2016                                tempword =
2017                                        ft1000_read_reg(dev, FT1000_REG_MAG_DFSR);
2018                        }
2019                        if (tempword & 0x1f) {
2020                                ft1000_copy_up_pkt(dev);
2021                        } else {
2022                                break;
2023                        }
2024                        cnt++;
2025                } while (cnt < MAX_RCV_LOOP);
2026
2027        }
2028        // clear interrupts
2029        tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
2030        DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
2031        ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
2032
2033        // Read interrupt type
2034        inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR);
2035        DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype);
2036    }
2037        ft1000_enable_interrupts(dev);
2038        return IRQ_HANDLED;
2039}
2040
2041void stop_ft1000_card(struct net_device *dev)
2042{
2043        struct ft1000_info *info = netdev_priv(dev);
2044        struct prov_record *ptr;
2045//      int cnt;
2046
2047        DEBUG(0, "ft1000_hw: stop_ft1000_card()\n");
2048
2049        info->CardReady = 0;
2050        ft1000_card_present = 0;
2051        netif_stop_queue(dev);
2052        ft1000_disable_interrupts(dev);
2053
2054        // Make sure we free any memory reserve for provisioning
2055        while (list_empty(&info->prov_list) == 0) {
2056                ptr = list_entry(info->prov_list.next, struct prov_record, list);
2057                list_del(&ptr->list);
2058                kfree(ptr->pprov_data);
2059                kfree(ptr);
2060        }
2061
2062        if (info->registered) {
2063                unregister_netdev(dev);
2064                info->registered = 0;
2065        }
2066
2067        free_irq(dev->irq, dev);
2068        release_region(dev->base_addr,256);
2069        release_firmware(fw_entry);
2070        flarion_ft1000_cnt--;
2071        ft1000CleanupProc(dev);
2072
2073}
2074
2075static void ft1000_get_drvinfo(struct net_device *dev,
2076                                   struct ethtool_drvinfo *info)
2077{
2078        struct ft1000_info *ft_info;
2079        ft_info = netdev_priv(dev);
2080
2081        snprintf(info->driver, 32, "ft1000");
2082        snprintf(info->bus_info, ETHTOOL_BUSINFO_LEN, "PCMCIA 0x%lx",
2083                 dev->base_addr);
2084        snprintf(info->fw_version, 32, "%d.%d.%d.%d", ft_info->DspVer[0],
2085                 ft_info->DspVer[1], ft_info->DspVer[2], ft_info->DspVer[3]);
2086}
2087
2088static u32 ft1000_get_link(struct net_device *dev)
2089{
2090        struct ft1000_info *info;
2091        info = netdev_priv(dev);
2092        return info->mediastate;
2093}
2094
2095static const struct ethtool_ops ops = {
2096        .get_drvinfo = ft1000_get_drvinfo,
2097        .get_link = ft1000_get_link
2098};
2099
2100struct net_device *init_ft1000_card(struct pcmcia_device *link,
2101                                                void *ft1000_reset)
2102{
2103        struct ft1000_info *info;
2104        struct net_device *dev;
2105
2106        static const struct net_device_ops ft1000ops =          // Slavius 21.10.2009 due to kernel changes
2107        {
2108                .ndo_open = &ft1000_open,
2109                .ndo_stop = &ft1000_close,
2110                .ndo_start_xmit = &ft1000_start_xmit,
2111                .ndo_get_stats = &ft1000_stats,
2112        };
2113
2114        DEBUG(1, "ft1000_hw: init_ft1000_card()\n");
2115        DEBUG(1, "ft1000_hw: irq = %d\n", link->irq);
2116        DEBUG(1, "ft1000_hw: port = 0x%04x\n", link->resource[0]->start);
2117
2118        flarion_ft1000_cnt++;
2119
2120        if (flarion_ft1000_cnt > 1) {
2121                flarion_ft1000_cnt--;
2122
2123                printk(KERN_INFO
2124                           "ft1000: This driver can not support more than one instance\n");
2125                return NULL;
2126        }
2127
2128        dev = alloc_etherdev(sizeof(struct ft1000_info));
2129        if (!dev) {
2130                printk(KERN_ERR "ft1000: failed to allocate etherdev\n");
2131                return NULL;
2132        }
2133
2134        SET_NETDEV_DEV(dev, &link->dev);
2135        info = netdev_priv(dev);
2136
2137        memset(info, 0, sizeof(struct ft1000_info));
2138
2139        DEBUG(1, "address of dev = 0x%8x\n", (u32) dev);
2140        DEBUG(1, "address of dev info = 0x%8x\n", (u32) info);
2141        DEBUG(0, "device name = %s\n", dev->name);
2142
2143        memset(&info->stats, 0, sizeof(struct net_device_stats));
2144
2145        spin_lock_init(&info->dpram_lock);
2146        info->DrvErrNum = 0;
2147        info->registered = 1;
2148        info->link = link;
2149        info->ft1000_reset = ft1000_reset;
2150        info->mediastate = 0;
2151        info->fifo_cnt = 0;
2152        info->CardReady = 0;
2153        info->DSP_TIME[0] = 0;
2154        info->DSP_TIME[1] = 0;
2155        info->DSP_TIME[2] = 0;
2156        info->DSP_TIME[3] = 0;
2157        flarion_ft1000_cnt = 0;
2158
2159        INIT_LIST_HEAD(&info->prov_list);
2160
2161        info->squeseqnum = 0;
2162
2163//      dev->hard_start_xmit = &ft1000_start_xmit;
2164//      dev->get_stats = &ft1000_stats;
2165//      dev->open = &ft1000_open;
2166//      dev->stop = &ft1000_close;
2167
2168        dev->netdev_ops = &ft1000ops;           // Slavius 21.10.2009 due to kernel changes
2169
2170        DEBUG(0, "device name = %s\n", dev->name);
2171
2172        dev->irq = link->irq;
2173        dev->base_addr = link->resource[0]->start;
2174        if (pcmcia_get_mac_from_cis(link, dev)) {
2175                printk(KERN_ERR "ft1000: Could not read mac address\n");
2176                goto err_dev;
2177        }
2178
2179        if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) {
2180                printk(KERN_ERR "ft1000: Could not request_irq\n");
2181                goto err_dev;
2182        }
2183
2184        if (request_region(dev->base_addr, 256, dev->name) == NULL) {
2185                printk(KERN_ERR "ft1000: Could not request_region\n");
2186                goto err_irq;
2187        }
2188
2189        if (register_netdev(dev) != 0) {
2190                DEBUG(0, "ft1000: Could not register netdev");
2191                goto err_reg;
2192        }
2193
2194        info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
2195        if (info->AsicID == ELECTRABUZZ_ID) {
2196                DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
2197                if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) {
2198                        printk(KERN_INFO "ft1000: Could not open ft1000.img\n");
2199                        goto err_unreg;
2200                }
2201        } else {
2202                DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n");
2203                if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) {
2204                        printk(KERN_INFO "ft1000: Could not open ft2000.img\n");
2205                        goto err_unreg;
2206                }
2207        }
2208
2209        ft1000_enable_interrupts(dev);
2210
2211        ft1000InitProc(dev);
2212        ft1000_card_present = 1;
2213        SET_ETHTOOL_OPS(dev, &ops);
2214        printk(KERN_INFO
2215                   "ft1000: %s: addr 0x%04lx irq %d, MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
2216                   dev->name, dev->base_addr, dev->irq, dev->dev_addr[0],
2217                   dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3],
2218                   dev->dev_addr[4], dev->dev_addr[5]);
2219        return dev;
2220
2221err_unreg:
2222        unregister_netdev(dev);
2223err_reg:
2224        release_region(dev->base_addr, 256);
2225err_irq:
2226        free_irq(dev->irq, dev);
2227err_dev:
2228        free_netdev(dev);
2229        return NULL;
2230}
2231
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.