source "drivers/staging/emxx_udc/Kconfig"
-source "drivers/staging/ft1000/Kconfig"
-
source "drivers/staging/speakup/Kconfig"
source "drivers/staging/ste_rmi4/Kconfig"
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
-obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_MFD_NVEC) += nvec/
+++ /dev/null
-config FT1000
- tristate "Drivers for Flarion ft1000 devices"
-
-if FT1000
-
-config FT1000_USB
- tristate "Driver for ft1000 usb devices."
- depends on USB
- depends on NET
- help
- Say Y if you want to have support for Qleadtek FLASH-OFDM USB Modem [LR7F04],
- Qleadtek Express Card or Leadtek Multi-band modem HSDPA.
-
-config FT1000_PCMCIA
- tristate "Driver for ft1000 pcmcia device."
- depends on PCMCIA
- depends on NET
- help
- Say Y if you want to have support for Flarion card also called
- Multimedia Net Card.
-
-endif
+++ /dev/null
-obj-$(CONFIG_FT1000_USB) += ft1000-usb/
-obj-$(CONFIG_FT1000_PCMCIA) += ft1000-pcmcia/
-
+++ /dev/null
-TODO:
- - checkpatch.pl cleanups
- - coding style
- - sparse fixes
- - adapt to latest usb and pcmcia api changes
- - change firmware loading for usb driver to proper kernel method (request_firmware)
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-Cc: Marek Belisko <marek.belisko@gmail.com>
+++ /dev/null
-obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o
-ft1000_pcmcia-y := ft1000_hw.o ft1000_dnld.o ft1000_cs.o
+++ /dev/null
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option) any
- later version. This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details. You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place -
- Suite 330, Boston, MA 02111-1307, USA.
- ---------------------------------------------------------------------------
-
- File: boot.h
-
- Description: boatloader
-
- History:
- 1/11/05 Whc Ported to Linux.
-
- ---------------------------------------------------------------------------*/
-#ifndef _BOOTH_
-#define _BOOTH_
-
-/* Official bootloader */
-static unsigned char bootimage[] = {
- 0x00, 0x00, 0x01, 0x5E, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0xD7,
- 0x00, 0x00, 0x01, 0x5E, 0x46, 0xB3,
- 0xE6, 0x02, 0x00, 0x98, 0xE6, 0x8C,
- 0x00, 0x98, 0xFB, 0x92, 0xFF, 0xFF,
- 0x98, 0xFB, 0x94, 0xFF, 0xFF, 0x98,
- 0xFB, 0x06, 0x08, 0x00, 0x98, 0xFB,
- 0x96, 0x84, 0x00, 0x98, 0xFB, 0x08,
- 0x1C, 0x00, 0x98, 0xFB, 0x51, 0x25,
- 0x10, 0x1C, 0x00, 0xE6, 0x51, 0x01,
- 0x07, 0xFD, 0x4C, 0xFF, 0x20, 0xF5,
- 0x51, 0x02, 0x20, 0x08, 0x00, 0x4C,
- 0xFF, 0x20, 0x3C, 0x00, 0xC0, 0x64,
- 0x98, 0xC0, 0x66, 0x98, 0xC0, 0x68,
- 0x98, 0xC0, 0x6A, 0x98, 0xC0, 0x6C,
- 0x98, 0x90, 0x08, 0x90, 0x09, 0x90,
- 0x0A, 0x90, 0x0B, 0x90, 0x0C, 0x90,
- 0x0D, 0x90, 0x0E, 0x90, 0x0F, 0x90,
- 0x04, 0x90, 0x06, 0xFB, 0x51, 0x22,
- 0x16, 0x08, 0x03, 0xFB, 0x51, 0x52,
- 0x16, 0x08, 0x04, 0xFB, 0x51, 0x24,
- 0x2B, 0x08, 0x06, 0xFB, 0x51, 0x54,
- 0x2B, 0x08, 0x07, 0xFB, 0x51, 0x24,
- 0x2B, 0x08, 0x09, 0xFB, 0x51, 0x54,
- 0x2B, 0x08, 0x0A, 0xFB, 0x51, 0x12,
- 0x16, 0x08, 0x0C, 0xFB, 0x51, 0x52,
- 0x16, 0x08, 0x0D, 0x78, 0x00, 0x00,
- 0x00, 0x16, 0x00, 0x00, 0xEC, 0x31,
- 0xAE, 0x00, 0x00, 0x81, 0x4C, 0x0F,
- 0xE6, 0x43, 0xFF, 0xEC, 0x31, 0x4E,
- 0x00, 0x00, 0x91, 0xEC, 0x31, 0xAE,
- 0x00, 0x00, 0x91, 0x4C, 0x0F, 0xE6,
- 0x43, 0xFF, 0xEC, 0x31, 0x5E, 0x00,
- 0x00, 0xA1, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xA6, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xAC, 0x3C, 0x00, 0xEB, 0x31,
- 0x08, 0x00, 0x00, 0xA8, 0x76, 0xFE,
- 0xFE, 0x08, 0xEB, 0x31, 0x08, 0x20,
- 0x00, 0x00, 0x76, 0xFF, 0xFF, 0x18,
- 0xED, 0x31, 0x08, 0x20, 0x00, 0x00,
- 0x26, 0x10, 0x04, 0x10, 0xF5, 0x3C,
- 0x01, 0x3C, 0x00, 0x08, 0x01, 0x12,
- 0x3C, 0x11, 0x3C, 0x00, 0x08, 0x01,
- 0x0B, 0x08, 0x00, 0x6D, 0xEC, 0x31,
- 0xAE, 0x20, 0x00, 0x06, 0xED, 0x4D,
- 0x08, 0x00, 0x00, 0x67, 0x80, 0x6F,
- 0x00, 0x01, 0x0B, 0x6F, 0x00, 0x02,
- 0x2E, 0x76, 0xEE, 0x01, 0x48, 0x06,
- 0x01, 0x39, 0xED, 0x4D, 0x18, 0x00,
- 0x02, 0xED, 0x4D, 0x08, 0x00, 0x04,
- 0x14, 0x06, 0xA4, 0xED, 0x31, 0x22,
- 0x00, 0x00, 0xAC, 0x76, 0xEE, 0x07,
- 0x48, 0x6D, 0x22, 0x01, 0x1E, 0x08,
- 0x01, 0x58, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xAC, 0x06, 0xFF, 0xBA, 0x3C,
- 0x00, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x30, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x00,
- 0x00, 0xA2, 0x91, 0x00, 0x9C, 0x3C,
- 0x80, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20,
- 0x00, 0x04, 0x42, 0x10, 0x90, 0x08,
- 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06,
- 0xA4, 0x41, 0x08, 0x00, 0xB6, 0xED,
- 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22,
- 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB,
- 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05,
- 0xFF, 0xE6, 0xA0, 0x31, 0x20, 0x00,
- 0x06, 0xEB, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x00, 0x04,
- 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20,
- 0x00, 0x04, 0x42, 0x10, 0x90, 0x08,
- 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06,
- 0xA4, 0x41, 0x08, 0x00, 0x68, 0xED,
- 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22,
- 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB,
- 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05,
- 0xFF, 0xE6, 0x48, 0x04, 0xEB, 0x31,
- 0x08, 0x20, 0x00, 0x04, 0xEB, 0x31,
- 0x18, 0x20, 0x00, 0x02, 0x3C, 0x11,
- 0xEB, 0x31, 0x18, 0x20, 0x00, 0x00,
- 0xED, 0x31, 0x08, 0x20, 0x00, 0x00,
- 0x04, 0x10, 0xF7, 0xED, 0x31, 0x08,
- 0x20, 0x00, 0x02, 0x66, 0x00, 0x6F,
- 0x00, 0x01, 0x16, 0x76, 0xEE, 0x06,
- 0x48, 0x4A, 0x1E, 0x48, 0x04, 0xED,
- 0x31, 0x08, 0x20, 0x00, 0x04, 0xEB,
- 0x31, 0x08, 0x00, 0x00, 0xA4, 0x48,
- 0x04, 0xED, 0x31, 0x08, 0x20, 0x00,
- 0x04, 0xEB, 0x31, 0x08, 0x00, 0x00,
- 0xA2, 0x48, 0x04, 0x20, 0x20, 0x4A,
- 0x7C, 0x46, 0x82, 0x50, 0x05, 0x50,
- 0x15, 0xB5, 0x1E, 0x98, 0xED, 0x31,
- 0x08, 0x00, 0x00, 0xA8, 0x10, 0x47,
- 0x3B, 0x2C, 0x01, 0xDB, 0x40, 0x11,
- 0x98, 0xC1, 0x1E, 0x98, 0x10, 0x07,
- 0x30, 0xF9, 0x40, 0x07, 0x18, 0x98,
- 0x2A, 0x10, 0xEB, 0x31, 0x08, 0x00,
- 0x00, 0xA8, 0xA4, 0x1E, 0x98, 0xBB,
- 0x1E, 0x98, 0x50, 0x14, 0x50, 0x04,
- 0x46, 0x83, 0x48, 0x04, 0x02, 0x01,
- 0x00, 0x50, 0x05, 0x50, 0x15, 0x10,
- 0x87, 0x3F, 0x90, 0x2B, 0x18, 0x01,
- 0x00, 0xC0, 0x31, 0x00, 0x00, 0xAE,
- 0xDF, 0x41, 0x00, 0x08, 0x00, 0x1A,
- 0x42, 0x11, 0x67, 0x01, 0xDF, 0x41,
- 0x02, 0x08, 0x00, 0x10, 0x42, 0x11,
- 0x62, 0x01, 0xB4, 0x43, 0x4A, 0x68,
- 0x50, 0x14, 0x50, 0x04, 0x24, 0x10,
- 0x48, 0x04, 0xF2, 0x31, 0x00, 0x01,
- 0x00, 0x00, 0xAE, 0xF6, 0x31, 0x00,
- 0x01, 0x00, 0x00, 0xAE, 0x62, 0xE4,
- 0xE5, 0x61, 0x04, 0x48, 0x04, 0xE5,
- 0x63, 0x05, 0x48, 0x04, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0x00
-};
-
-#endif
+++ /dev/null
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option) any
- later version. This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details. You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place -
- Suite 330, Boston, MA 02111-1307, USA.
- ---------------------------------------------------------------------------
- Description: Common structures and defines
- ---------------------------------------------------------------------------*/
-#ifndef _FT1000H_
-#define _FT1000H_
-
-#include "../ft1000.h"
-
-#define FT1000_DRV_VER 0x01010300
-
-#define FT1000_DPRAM_BASE 0x0000 /* Dual Port RAM starting offset */
-
-/*
- * Maximum number of occurrence of pseudo header errors before resetting PC
- * Card.
- */
-#define MAX_PH_ERR 300
-
-#define SUCCESS 0x00
-#define FAILURE 0x01
-
-struct ft1000_pcmcia {
- int PktIntfErr;
- u16 packetseqnum;
- void *link;
-};
-
-struct pcmcia_device;
-struct net_device;
-struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset);
-void stop_ft1000_card(struct net_device *dev);
-int card_download(struct net_device *dev, const u8 *pFileStart,
- size_t FileLength);
-
-u16 ft1000_read_dpram(struct net_device *dev, int offset);
-void card_bootload(struct net_device *dev);
-u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
-u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
-void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
-
-/* Read the value of a given ASIC register. */
-static inline u16 ft1000_read_reg(struct net_device *dev, u16 offset)
-{
- return inw(dev->base_addr + offset);
-}
-
-/* Set the value of a given ASIC register. */
-static inline void ft1000_write_reg(struct net_device *dev, u16 offset,
- u16 value)
-{
- outw(value, dev->base_addr + offset);
-}
-
-#endif
+++ /dev/null
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
- Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
- Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds.
-
- This file was modified to support the Flarion Flash OFDM NIC Device
- by Wai Chan (w.chan@flarion.com).
-
- Port for kernel 2.6 created by Patrik Ostrihon (patrik.ostrihon@pwc.sk)
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option) any
- later version. This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details. You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place -
- Suite 330, Boston, MA 02111-1307, USA.
- -----------------------------------------------------------------------------*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-/*====================================================================*/
-
-MODULE_AUTHOR("Wai Chan");
-MODULE_DESCRIPTION("FT1000 PCMCIA driver");
-MODULE_LICENSE("GPL");
-
-/*====================================================================*/
-
-static int ft1000_config(struct pcmcia_device *link);
-static void ft1000_detach(struct pcmcia_device *link);
-static int ft1000_attach(struct pcmcia_device *link);
-
-#include "ft1000.h"
-
-/*====================================================================*/
-
-static void ft1000_reset(struct pcmcia_device *link)
-{
- pcmcia_reset_card(link->socket);
-}
-
-static int ft1000_attach(struct pcmcia_device *link)
-{
- link->priv = NULL;
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- return ft1000_config(link);
-}
-
-static void ft1000_detach(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (dev)
- stop_ft1000_card(dev);
-
- pcmcia_disable_device(link);
- free_netdev(dev);
-}
-
-static int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
-{
- return pcmcia_request_io(link);
-}
-
-/*======================================================================
-
- ft1000_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
- ======================================================================*/
-
-static int ft1000_config(struct pcmcia_device *link)
-{
- int ret;
-
- dev_dbg(&link->dev, "ft1000_cs: ft1000_config(0x%p)\n", link);
-
- /* setup IO window */
- ret = pcmcia_loop_config(link, ft1000_confcheck, NULL);
- if (ret) {
- dev_err(&link->dev, "Could not configure pcmcia\n");
- return -ENODEV;
- }
-
- /* configure device */
- ret = pcmcia_enable_device(link);
- if (ret) {
- dev_err(&link->dev, "Could not enable pcmcia\n");
- goto failed;
- }
-
- link->priv = init_ft1000_card(link, &ft1000_reset);
- if (!link->priv) {
- dev_err(&link->dev, "Could not register as network device\n");
- goto failed;
- }
-
- /* Finally, report what we've done */
-
- return 0;
-failed:
- pcmcia_disable_device(link);
- return -ENODEV;
-}
-
-static int ft1000_suspend(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (link->open)
- netif_device_detach(dev);
- return 0;
-}
-
-static int ft1000_resume(struct pcmcia_device *link)
-{
- return 0;
-}
-
-/*====================================================================*/
-
-static const struct pcmcia_device_id ft1000_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x0100),
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1000),
- PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1300),
- PCMCIA_DEVICE_NULL,
-};
-
-MODULE_DEVICE_TABLE(pcmcia, ft1000_ids);
-
-static struct pcmcia_driver ft1000_cs_driver = {
- .owner = THIS_MODULE,
- .name = "ft1000_cs",
- .probe = ft1000_attach,
- .remove = ft1000_detach,
- .id_table = ft1000_ids,
- .suspend = ft1000_suspend,
- .resume = ft1000_resume,
-};
-
-module_pcmcia_driver(ft1000_cs_driver);
+++ /dev/null
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option) any
- later version. This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details. You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place -
- Suite 330, Boston, MA 02111-1307, USA.
- --------------------------------------------------------------------------
-
- Description: This module will handshake with the DSP bootloader to
- download the DSP runtime image.
-
- ---------------------------------------------------------------------------*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define __KERNEL_SYSCALLS__
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/unistd.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-
-#include "ft1000.h"
-#include "boot.h"
-
-#define MAX_DSP_WAIT_LOOPS 100
-#define DSP_WAIT_SLEEP_TIME 1 /* 1 millisecond */
-
-#define MAX_LENGTH 0x7f0
-
-#define DWNLD_MAG_HANDSHAKE_LOC 0x00
-#define DWNLD_MAG_TYPE_LOC 0x01
-#define DWNLD_MAG_SIZE_LOC 0x02
-#define DWNLD_MAG_PS_HDR_LOC 0x03
-
-#define DWNLD_HANDSHAKE_LOC 0x02
-#define DWNLD_TYPE_LOC 0x04
-#define DWNLD_SIZE_MSW_LOC 0x06
-#define DWNLD_SIZE_LSW_LOC 0x08
-#define DWNLD_PS_HDR_LOC 0x0A
-
-#define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
-#define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
-#define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
-#define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
-
-#define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
-#define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
-
-#define REQUEST_CODE_LENGTH 0x0000
-#define REQUEST_RUN_ADDRESS 0x0001
-#define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
-#define REQUEST_DONE_BL 0x0003
-#define REQUEST_DONE_CL 0x0004
-#define REQUEST_VERSION_INFO 0x0005
-#define REQUEST_CODE_BY_VERSION 0x0006
-#define REQUEST_MAILBOX_DATA 0x0007
-#define REQUEST_FILE_CHECKSUM 0x0008
-
-#define STATE_START_DWNLD 0x01
-#define STATE_BOOT_DWNLD 0x02
-#define STATE_CODE_DWNLD 0x03
-#define STATE_DONE_DWNLD 0x04
-#define STATE_SECTION_PROV 0x05
-#define STATE_DONE_PROV 0x06
-#define STATE_DONE_FILE 0x07
-
-struct dsp_file_hdr {
- u32 version_id; /* Version ID of this image format. */
- u32 package_id; /* Package ID of code release. */
- u32 build_date; /* Date/time stamp when file was built. */
- u32 commands_offset; /* Offset to attached commands in Pseudo Hdr format. */
- u32 loader_offset; /* Offset to bootloader code. */
- u32 loader_code_address; /* Start address of bootloader. */
- u32 loader_code_end; /* Where bootloader code ends. */
- u32 loader_code_size;
- u32 version_data_offset; /* Offset were scrambled version data begins. */
- u32 version_data_size; /* Size, in words, of scrambled version data. */
- u32 nDspImages; /* Number of DSP images in file. */
-} __packed;
-
-struct dsp_image_info {
- u32 coff_date; /* Date/time when DSP Coff image was built. */
- u32 begin_offset; /* Offset in file where image begins. */
- u32 end_offset; /* Offset in file where image begins. */
- u32 run_address; /* On chip Start address of DSP code. */
- u32 image_size; /* Size of image. */
- u32 version; /* Embedded version # of DSP code. */
- unsigned short checksum; /* Dsp File checksum */
- unsigned short pad1;
-} __packed;
-
-void card_bootload(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u32 *pdata;
- u32 size;
- u32 i;
- u32 templong;
-
- netdev_dbg(dev, "card_bootload is called\n");
-
- pdata = (u32 *)bootimage;
- size = sizeof(bootimage);
-
- /* check for odd word */
- if (size & 0x0003)
- size += 4;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
-
- /* need to set i/o base address initially and hardware will autoincrement */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_BASE);
- /* write bytes */
- for (i = 0; i < (size >> 2); i++) {
- templong = *pdata++;
- outl(templong, dev->base_addr + FT1000_REG_MAG_DPDATA);
- }
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-static u16 get_handshake(struct net_device *dev, u16 expected_value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 handshake;
- u32 tempx;
- int loopcnt;
-
- loopcnt = 0;
- while (loopcnt < MAX_DSP_WAIT_LOOPS) {
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_HANDSHAKE_LOC);
-
- handshake = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- } else {
- tempx =
- ntohl(ft1000_read_dpram_mag_32
- (dev, DWNLD_MAG_HANDSHAKE_LOC));
- handshake = (u16)tempx;
- }
-
- if ((handshake == expected_value)
- || (handshake == HANDSHAKE_RESET_VALUE)) {
- return handshake;
- }
- loopcnt++;
- mdelay(DSP_WAIT_SLEEP_TIME);
-
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-
-}
-
-static void put_handshake(struct net_device *dev, u16 handshake_value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_HANDSHAKE_LOC);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value); /* Handshake */
- } else {
- tempx = (u32)handshake_value;
- tempx = ntohl(tempx);
- ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */
- }
-}
-
-static u16 get_request_type(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 request_type;
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC);
- request_type = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- } else {
- tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC);
- tempx = ntohl(tempx);
- request_type = (u16)tempx;
- }
-
- return request_type;
-
-}
-
-static long get_request_value(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- long value;
- u16 w_val;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_MSW_LOC);
-
- w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-
- value = (long)(w_val << 16);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_LSW_LOC);
-
- w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-
- value = (long)(value | w_val);
- } else {
- value = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC);
- value = ntohl(value);
- }
-
- return value;
-
-}
-
-static void put_request_value(struct net_device *dev, long lvalue)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 size;
- u32 tempx;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- size = (u16) (lvalue >> 16);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_MSW_LOC);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
-
- size = (u16) (lvalue);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- DWNLD_SIZE_LSW_LOC);
-
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
- } else {
- tempx = ntohl(lvalue);
- ft1000_write_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC, tempx); /* Handshake */
- }
-
-}
-
-static u16 hdr_checksum(struct pseudo_hdr *pHdr)
-{
- u16 *usPtr = (u16 *)pHdr;
- u16 chksum;
-
- chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
- usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
-
- return chksum;
-}
-
-int card_download(struct net_device *dev, const u8 *pFileStart,
- size_t FileLength)
-{
- struct ft1000_info *info = netdev_priv(dev);
- int Status = SUCCESS;
- u32 uiState;
- u16 handshake;
- struct pseudo_hdr *pHdr;
- u16 usHdrLength;
- long word_length;
- u16 request;
- u16 temp;
- struct prov_record *pprov_record;
- u8 *pbuffer;
- struct dsp_file_hdr *pFileHdr5;
- struct dsp_image_info *pDspImageInfoV6 = NULL;
- long requested_version;
- bool bGoodVersion = false;
- struct drv_msg *pMailBoxData;
- u16 *pUsData = NULL;
- u16 *pUsFile = NULL;
- u8 *pUcFile = NULL;
- u8 *pBootEnd = NULL;
- u8 *pCodeEnd = NULL;
- int imageN;
- long file_version;
- long loader_code_address = 0;
- long loader_code_size = 0;
- long run_address = 0;
- long run_size = 0;
- unsigned long flags;
- unsigned long templong;
- unsigned long image_chksum = 0;
-
- file_version = *(long *)pFileStart;
- if (file_version != 6) {
- pr_err("unsupported firmware version %ld\n", file_version);
- Status = FAILURE;
- }
-
- uiState = STATE_START_DWNLD;
-
- pFileHdr5 = (struct dsp_file_hdr *)pFileStart;
-
- pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->loader_offset);
- pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->loader_offset);
- pBootEnd = (u8 *) ((long)pFileStart + pFileHdr5->loader_code_end);
- loader_code_address = pFileHdr5->loader_code_address;
- loader_code_size = pFileHdr5->loader_code_size;
- bGoodVersion = false;
-
- while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
-
- switch (uiState) {
- case STATE_START_DWNLD:
-
- handshake = get_handshake(dev, HANDSHAKE_DSP_BL_READY);
-
- if (handshake == HANDSHAKE_DSP_BL_READY)
- put_handshake(dev, HANDSHAKE_DRIVER_READY);
- else
- Status = FAILURE;
-
- uiState = STATE_BOOT_DWNLD;
-
- break;
-
- case STATE_BOOT_DWNLD:
- handshake = get_handshake(dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(dev);
- switch (request) {
- case REQUEST_RUN_ADDRESS:
- put_request_value(dev,
- loader_code_address);
- break;
- case REQUEST_CODE_LENGTH:
- put_request_value(dev,
- loader_code_size);
- break;
- case REQUEST_DONE_BL:
- /* Reposition ptrs to beginning of code section */
- pUsFile = (u16 *) ((long)pBootEnd);
- pUcFile = (u8 *) ((long)pBootEnd);
- uiState = STATE_CODE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- word_length = get_request_value(dev);
- if (word_length > MAX_LENGTH) {
- Status = FAILURE;
- break;
- }
- if ((word_length * 2 + (long)pUcFile) >
- (long)pBootEnd) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
- default:
- Status = FAILURE;
- break;
- }
- put_handshake(dev, HANDSHAKE_RESPONSE);
- } else {
- Status = FAILURE;
- }
-
- break;
-
- case STATE_CODE_DWNLD:
- handshake = get_handshake(dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(dev);
- switch (request) {
- case REQUEST_FILE_CHECKSUM:
- netdev_dbg(dev,
- "ft1000_dnld: REQUEST_FOR_CHECKSUM\n");
- put_request_value(dev, image_chksum);
- break;
- case REQUEST_RUN_ADDRESS:
- if (bGoodVersion) {
- put_request_value(dev,
- run_address);
- } else {
- Status = FAILURE;
- break;
- }
- break;
- case REQUEST_CODE_LENGTH:
- if (bGoodVersion) {
- put_request_value(dev,
- run_size);
- } else {
- Status = FAILURE;
- break;
- }
- break;
- case REQUEST_DONE_CL:
- /* Reposition ptrs to beginning of provisioning section */
- pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->commands_offset);
- pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->commands_offset);
- uiState = STATE_DONE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- if (!bGoodVersion) {
- Status = FAILURE;
- break;
- }
- word_length = get_request_value(dev);
- if (word_length > MAX_LENGTH) {
- Status = FAILURE;
- break;
- }
- if ((word_length * 2 + (long)pUcFile) >
- (long)pCodeEnd) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsFile++;
- templong |=
- (*pUsFile++ << 16);
- pUcFile += 4;
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- break;
-
- case REQUEST_MAILBOX_DATA:
- /* Convert length from byte count to word count. Make sure we round up. */
- word_length =
- (long)(info->DSPInfoBlklen + 1) / 2;
- put_request_value(dev, word_length);
- pMailBoxData =
- (struct drv_msg *)&info->DSPInfoBlk[0];
- pUsData =
- (u16 *)&pMailBoxData->data[0];
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- if (file_version == 5) {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_ADDR,
- DWNLD_PS_HDR_LOC);
-
- for (; word_length > 0; word_length--) { /* In words */
- temp = ntohs(*pUsData);
- ft1000_write_reg(dev,
- FT1000_REG_DPRAM_DATA,
- temp);
- pUsData++;
- }
- } else {
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong = *pUsData++;
- templong |=
- (*pUsData++ << 16);
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
-
- case REQUEST_VERSION_INFO:
- word_length =
- pFileHdr5->version_data_size;
- put_request_value(dev, word_length);
- pUsFile =
- (u16 *) ((long)pFileStart +
- pFileHdr5->
- version_data_offset);
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock,
- flags);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
- outw(DWNLD_MAG_PS_HDR_LOC,
- dev->base_addr +
- FT1000_REG_DPRAM_ADDR);
- if (word_length & 0x01)
- word_length++;
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
- templong =
- ntohs(*pUsFile++);
- temp =
- ntohs(*pUsFile++);
- templong |=
- (temp << 16);
- outl(templong,
- dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- }
- spin_unlock_irqrestore(&info->
- dpram_lock,
- flags);
- break;
-
- case REQUEST_CODE_BY_VERSION:
- bGoodVersion = false;
- requested_version =
- get_request_value(dev);
- pDspImageInfoV6 =
- (struct dsp_image_info *) ((long)
- pFileStart
- +
- sizeof
- (struct dsp_file_hdr));
- for (imageN = 0;
- imageN <
- pFileHdr5->nDspImages;
- imageN++) {
- temp = (u16)
- (pDspImageInfoV6->
- version);
- templong = temp;
- temp = (u16)
- (pDspImageInfoV6->
- version >> 16);
- templong |=
- (temp << 16);
- if (templong ==
- requested_version) {
- bGoodVersion =
- true;
- pUsFile =
- (u16
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pUcFile =
- (u8
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- begin_offset);
- pCodeEnd =
- (u8
- *) ((long)
- pFileStart
- +
- pDspImageInfoV6->
- end_offset);
- run_address =
- pDspImageInfoV6->
- run_address;
- run_size =
- pDspImageInfoV6->
- image_size;
- image_chksum =
- (u32)
- pDspImageInfoV6->
- checksum;
- netdev_dbg(dev,
- "ft1000_dnld: image_chksum = 0x%8x\n",
- (unsigned
- int)
- image_chksum);
- break;
- }
- pDspImageInfoV6++;
- }
- if (!bGoodVersion) {
- /*
- * Error, beyond boot code range.
- */
- Status = FAILURE;
- break;
- }
- break;
-
- default:
- Status = FAILURE;
- break;
- }
- put_handshake(dev, HANDSHAKE_RESPONSE);
- } else {
- Status = FAILURE;
- }
-
- break;
-
- case STATE_DONE_DWNLD:
- if (((unsigned long)(pUcFile) - (unsigned long) pFileStart) >=
- (unsigned long)FileLength) {
- uiState = STATE_DONE_FILE;
- break;
- }
-
- pHdr = (struct pseudo_hdr *)pUsFile;
-
- if (pHdr->portdest == 0x80 /* DspOAM */
- && (pHdr->portsrc == 0x00 /* Driver */
- || pHdr->portsrc == 0x10 /* FMM */)) {
- uiState = STATE_SECTION_PROV;
- } else {
- netdev_dbg(dev,
- "Download error: Bad Port IDs in Pseudo Record\n");
- netdev_dbg(dev, "\t Port Source = 0x%2.2x\n",
- pHdr->portsrc);
- netdev_dbg(dev, "\t Port Destination = 0x%2.2x\n",
- pHdr->portdest);
- Status = FAILURE;
- }
-
- break;
-
- case STATE_SECTION_PROV:
-
- pHdr = (struct pseudo_hdr *)pUcFile;
-
- if (pHdr->checksum == hdr_checksum(pHdr)) {
- if (pHdr->portdest != 0x80 /* Dsp OAM */) {
- uiState = STATE_DONE_PROV;
- break;
- }
- usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */
-
- /* Get buffer for provisioning data */
- pbuffer =
- kmalloc(usHdrLength + sizeof(struct pseudo_hdr),
- GFP_ATOMIC);
- if (pbuffer) {
- memcpy(pbuffer, pUcFile,
- (u32) (usHdrLength +
- sizeof(struct pseudo_hdr)));
- /* link provisioning data */
- pprov_record =
- kmalloc(sizeof(struct prov_record),
- GFP_ATOMIC);
- if (pprov_record) {
- pprov_record->pprov_data =
- pbuffer;
- list_add_tail(&pprov_record->
- list,
- &info->prov_list);
- /* Move to next entry if available */
- pUcFile =
- (u8 *)((unsigned long) pUcFile +
- (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
- if ((unsigned long) (pUcFile) -
- (unsigned long) (pFileStart) >=
- (unsigned long)FileLength) {
- uiState =
- STATE_DONE_FILE;
- }
- } else {
- kfree(pbuffer);
- Status = FAILURE;
- }
- } else {
- Status = FAILURE;
- }
- } else {
- /* Checksum did not compute */
- Status = FAILURE;
- }
-
- break;
-
- case STATE_DONE_PROV:
- uiState = STATE_DONE_FILE;
- break;
-
- default:
- Status = FAILURE;
- break;
- } /* End Switch */
-
- } /* End while */
-
- return Status;
-
-}
+++ /dev/null
-/*---------------------------------------------------------------------------
- FT1000 driver for Flarion Flash OFDM NIC Device
-
- Copyright (C) 2002 Flarion Technologies, All rights reserved.
- Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
- Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option) any
- later version. This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details. You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place -
- Suite 330, Boston, MA 02111-1307, USA.
- -------------------------------------------------------------------------*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/ioport.h>
-#include <linux/wait.h>
-#include <linux/vmalloc.h>
-
-#include <linux/firmware.h>
-#include <linux/ethtool.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ds.h>
-
-#include <linux/delay.h>
-#include "ft1000.h"
-
-static const struct firmware *fw_entry;
-
-static void ft1000_hbchk(u_long data);
-static struct timer_list poll_timer = {
- .function = ft1000_hbchk
-};
-
-static u16 cmdbuffer[1024];
-static u8 tempbuffer[1600];
-static u8 ft1000_card_present;
-static u8 flarion_ft1000_cnt;
-
-static irqreturn_t ft1000_interrupt(int irq, void *dev_id);
-static void ft1000_enable_interrupts(struct net_device *dev);
-static void ft1000_disable_interrupts(struct net_device *dev);
-
-/* new kernel */
-MODULE_AUTHOR("");
-MODULE_DESCRIPTION("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FT1000");
-
-#define MAX_RCV_LOOP 100
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_fifo_len
- Description: This function will read the ASIC Uplink FIFO status register
- which will return the number of bytes remaining in the Uplink FIFO.
- Sixteen bytes are subtracted to make sure that the ASIC does not
- reach its threshold.
- Input:
- dev - network device structure
- Output:
- value - number of bytes available in the ASIC Uplink FIFO.
-
- -------------------------------------------------------------------------*/
-static inline u16 ft1000_read_fifo_len(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- if (info->AsicID == ELECTRABUZZ_ID)
- return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
- else
- return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram
- Description: This function will read the specific area of dpram
- (Electrabuzz ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u16 ft1000_read_dpram(struct net_device *dev, int offset)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u16 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram
- Description: This function will write to a specific area of dpram
- (Electrabuzz ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-static inline void ft1000_write_dpram(struct net_device *dev,
- int offset, u16 value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram_mag_16
- Description: This function will read the specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u16 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- /* check if we want to read upper or lower 32-bit word */
- if (Index)
- data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL);
- else
- data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH);
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram_mag_16
- Description: This function will write to a specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
- int offset, u16 value, int Index)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- if (Index)
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value);
- else
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value);
-
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_read_dpram_mag_32
- Description: This function will read the specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- Output:
- value - value of dpram
-
- -------------------------------------------------------------------------*/
-u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
- u32 data;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- return data;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_write_dpram_mag_32
- Description: This function will write to a specific area of dpram
- (Magnemite ASIC only)
- Input:
- dev - device structure
- offset - index of dpram
- value - value to write
- Output:
- none.
-
- -------------------------------------------------------------------------*/
-void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
-{
- struct ft1000_info *info = netdev_priv(dev);
- unsigned long flags;
-
- /* Provide mutual exclusive access while reading ASIC registers. */
- spin_lock_irqsave(&info->dpram_lock, flags);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
- outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL);
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_enable_interrupts
- Description: This function will enable interrupts base on the current
- interrupt mask.
- Input:
- dev - device structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_enable_interrupts(struct net_device *dev)
-{
- u16 tempword;
-
- ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- pr_debug("current interrupt enable mask = 0x%x\n", tempword);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_disable_interrupts
- Description: This function will disable all interrupts.
- Input:
- dev - device structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_disable_interrupts(struct net_device *dev)
-{
- u16 tempword;
-
- ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- pr_debug("current interrupt enable mask = 0x%x\n", tempword);
-}
-
-/*---------------------------------------------------------------------------
- Function: ft1000_read_dsp_timer
- Description: This function reads the DSP timer and stores its value in the
- DSP_TIME field of the ft1000_info struct passed as argument
- Input:
- dev - device structure
- info - ft1000_info structure
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_read_dsp_timer(struct net_device *dev,
- struct ft1000_info *info)
-{
- if (info->AsicID == ELECTRABUZZ_ID) {
- info->DSP_TIME[0] = ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
- info->DSP_TIME[1] = ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
- info->DSP_TIME[2] = ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
- info->DSP_TIME[3] = ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
- } else {
- info->DSP_TIME[0] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
- FT1000_MAG_DSP_TIMER0_INDX);
- info->DSP_TIME[1] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
- FT1000_MAG_DSP_TIMER1_INDX);
- info->DSP_TIME[2] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
- FT1000_MAG_DSP_TIMER2_INDX);
- info->DSP_TIME[3] =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
- FT1000_MAG_DSP_TIMER3_INDX);
- }
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_reset_asic
- Description: This function will call the Card Service function to reset the
- ASIC.
- Input:
- dev - device structure
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_reset_asic(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- u16 tempword;
-
- (*info->ft1000_reset) (pcmcia->link);
-
- /*
- * Let's use the register provided by the Magnemite ASIC to reset the
- * ASIC and DSP.
- */
- if (info->AsicID == MAGNEMITE_ID) {
- ft1000_write_reg(dev, FT1000_REG_RESET,
- DSP_RESET_BIT | ASIC_RESET_BIT);
- }
- mdelay(1);
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff);
- } else {
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff);
- }
- /* clear interrupts */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_reset_card
- Description: This function will reset the card
- Input:
- dev - device structure
- Output:
- status - false (card reset fail)
- true (card reset successful)
-
- -------------------------------------------------------------------------*/
-static int ft1000_reset_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 tempword;
- int i;
- unsigned long flags;
- struct prov_record *ptr;
- struct prov_record *tmp;
-
- info->CardReady = 0;
- info->ProgConStat = 0;
- info->squeseqnum = 0;
- ft1000_disable_interrupts(dev);
-
- /* del_timer(&poll_timer); */
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- pr_debug("deleting provisioning record\n");
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- pr_debug("resetting DSP\n");
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
- } else {
- pr_debug("resetting ASIC and DSP\n");
- ft1000_write_reg(dev, FT1000_REG_RESET,
- DSP_RESET_BIT | ASIC_RESET_BIT);
- }
-
- /* Copy DSP session record into info block if this is not a coldstart */
- if (ft1000_card_present == 1) {
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC; i++) {
- info->DSPSess.Rec[i] =
- ft1000_read_reg(dev,
- FT1000_REG_DPRAM_DATA);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
- info->DSPSess.MagRec[i] =
- inl(dev->base_addr
- + FT1000_REG_MAG_DPDATA);
- }
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
- }
-
- pr_debug("resetting ASIC\n");
- mdelay(10);
- /* reset ASIC */
- ft1000_reset_asic(dev);
-
- pr_debug("downloading dsp image\n");
-
- if (info->AsicID == MAGNEMITE_ID) {
- /* Put dsp in reset and take ASIC out of reset */
- pr_debug("Put DSP in reset and take ASIC out of reset\n");
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
-
- /* Setting MAGNEMITE ASIC to big endian mode */
- ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE);
- /* Download bootloader */
- card_bootload(dev);
-
- /* Take DSP out of reset */
- ft1000_write_reg(dev, FT1000_REG_RESET, 0);
- /* FLARION_DSP_ACTIVE; */
- mdelay(10);
- pr_debug("Take DSP out of reset\n");
-
- /*
- * Wait for 0xfefe indicating dsp ready before starting
- * download
- */
- for (i = 0; i < 50; i++) {
- tempword = ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_DPRAM_FEFE,
- FT1000_MAG_DPRAM_FEFE_INDX);
- if (tempword == 0xfefe)
- break;
- mdelay(20);
- }
-
- if (i == 50) {
- pr_debug("No FEFE detected from DSP\n");
- return false;
- }
-
- } else {
- /* Take DSP out of reset */
- ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT);
- mdelay(10);
- }
-
- if (card_download(dev, fw_entry->data, fw_entry->size)) {
- pr_debug("card download unsuccessful\n");
- return false;
- }
- pr_debug("card download successful\n");
-
- mdelay(10);
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- /*
- * Need to initialize the FIFO length counter to zero in order
- * to sync up with the DSP
- */
- info->fifo_cnt = 0;
- ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
- /* Initialize DSP heartbeat area to ho */
- ft1000_write_dpram(dev, FT1000_HI_HO, ho);
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- pr_debug("hi_ho value = 0x%x\n", tempword);
- } else {
- /* Initialize DSP heartbeat area to ho */
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag,
- FT1000_MAG_HI_HO_INDX);
- tempword =
- ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX);
- pr_debug("hi_ho value = 0x%x\n", tempword);
- }
-
- info->CardReady = 1;
- ft1000_enable_interrupts(dev);
-
- /* Schedule heartbeat process to run every 2 seconds */
- /* poll_timer.expires = jiffies + (2*HZ); */
- /* poll_timer.data = (u_long)dev; */
- /* add_timer(&poll_timer); */
-
- return true;
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_chkcard
- Description: This function will check if the device is presently available on
- the system.
- Input:
- dev - device structure
- Output:
- status - false (device is not present)
- true (device is present)
-
- -------------------------------------------------------------------------*/
-static int ft1000_chkcard(struct net_device *dev)
-{
- u16 tempword;
-
- /*
- * Mask register is used to check for device presence since it is never
- * set to zero.
- */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- pr_debug("IMASK = 0 Card not detected\n");
- return false;
- }
- /*
- * The system will return the value of 0xffff for the version register
- * if the device is not present.
- */
- tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
- if (tempword == 0xffff) {
- pr_debug("Version = 0xffff Card not detected\n");
- return false;
- }
- return true;
-}
-
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_hbchk
- Description: This function will perform the heart beat check of the DSP as
- well as the ASIC.
- Input:
- dev - device structure
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_hbchk(u_long data)
-{
- struct net_device *dev = (struct net_device *)data;
-
- struct ft1000_info *info;
- u16 tempword;
-
- info = netdev_priv(dev);
-
- if (info->CardReady == 1) {
- /* Perform dsp heartbeat check */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- } else {
- tempword =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- pr_debug("hi_ho value = 0x%x\n", tempword);
- /* Let's perform another check if ho is not detected */
- if (tempword != ho) {
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- else
- tempword = ntohs(ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- if (tempword != ho) {
- pr_info("heartbeat failed - no ho detected\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
-
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- /* Let's check doorbell again if fail */
- if (tempword & FT1000_DB_HB)
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
-
- if (tempword & FT1000_DB_HB) {
- pr_info("heartbeat doorbell not clear by firmware\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
- /*
- * Set dedicated area to hi and ring appropriate doorbell
- * according to hi/ho heartbeat protocol
- */
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_dpram(dev, FT1000_HI_HO, hi);
- } else {
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag,
- FT1000_MAG_HI_HO_INDX);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- } else {
- tempword =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
- /* Let's write hi again if fail */
- if (tempword != hi) {
- if (info->AsicID == ELECTRABUZZ_ID)
- ft1000_write_dpram(dev, FT1000_HI_HO, hi);
- else
- ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO,
- hi_mag, FT1000_MAG_HI_HO_INDX);
-
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
- else
- tempword = ntohs(ft1000_read_dpram_mag_16(dev,
- FT1000_MAG_HI_HO,
- FT1000_MAG_HI_HO_INDX));
- }
-
- if (tempword != hi) {
- pr_info("heartbeat failed - cannot write hi into DPRAM\n");
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_HB_INFO;
- if (ft1000_reset_card(dev) == 0) {
- pr_info("Hardware Failure Detected - PC Card disabled\n");
- info->ProgConStat = 0xff;
- return;
- }
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2*HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
- return;
- }
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB);
-
- }
-
- /* Schedule this module to run every 2 seconds */
- poll_timer.expires = jiffies + (2 * HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_send_cmd
- Description:
- Input:
- Output:
-
- -------------------------------------------------------------------------*/
-static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size,
- u16 qtype)
-{
- struct ft1000_info *info = netdev_priv(dev);
- int i;
- u16 tempword;
- unsigned long flags;
-
- size += sizeof(struct pseudo_hdr);
- /* check for odd byte and increment to 16-bit word align value */
- if ((size & 0x0001))
- size++;
- pr_debug("total length = %d\n", size);
- pr_debug("length = %d\n", ntohs(*ptempbuffer));
- /*
- * put message into slow queue area
- * All messages are in the form total_len + pseudo header + message body
- */
- spin_lock_irqsave(&info->dpram_lock, flags);
-
- /* Make sure SLOWQ doorbell is clear */
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- i = 0;
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- i++;
- if (i == 10) {
- spin_unlock_irqrestore(&info->dpram_lock, flags);
- return;
- }
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- }
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_TX_BASE);
- /* Write total length to dpram */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
- /* Write pseudo header and messgae body */
- for (i = 0; i < (size >> 1); i++) {
- pr_debug("data %d = 0x%x\n", i, *ptempbuffer);
- tempword = htons(*ptempbuffer++);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_TX_BASE);
- /* Write total length to dpram */
- ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size));
- /* Write pseudo header and messgae body */
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_TX_BASE + 1);
- for (i = 0; i < (size >> 2); i++) {
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++,
- dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++,
- dev->base_addr + FT1000_REG_MAG_DPDATAH);
- }
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("data = 0x%x\n", *ptempbuffer);
- outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH);
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /* ring doorbell to notify DSP that we have a message ready */
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX);
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_receive_cmd
- Description: This function will read a message from the dpram area.
- Input:
- dev - network device structure
- pbuffer - caller supply address to buffer
- pnxtph - pointer to next pseudo header
- Output:
- Status = 0 (unsuccessful)
- = 1 (successful)
-
- -------------------------------------------------------------------------*/
-static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
- int maxsz, u16 *pnxtph)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 size;
- u16 *ppseudohdr;
- int i;
- u16 tempword;
- unsigned long flags;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- size = ft1000_read_dpram(dev, *pnxtph)
- + sizeof(struct pseudo_hdr);
- } else {
- size = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_PH_LEN,
- FT1000_MAG_PH_LEN_INDX))
- + sizeof(struct pseudo_hdr);
- }
- if (size > maxsz) {
- pr_debug("Invalid command length = %d\n", size);
- return false;
- }
- ppseudohdr = (u16 *)pbuffer;
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE + 2);
- for (i = 0; i <= (size >> 1); i++) {
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- *pbuffer++ = ntohs(tempword);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE + 1);
- for (i = 0; i <= (size >> 2); i++) {
- *pbuffer =
- inw(dev->base_addr +
- FT1000_REG_MAG_DPDATAL);
- pbuffer++;
- *pbuffer =
- inw(dev->base_addr +
- FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- }
- /* copy odd aligned word */
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
- pr_debug("received data = 0x%x\n", *pbuffer);
- pbuffer++;
- }
- if (size & 0x0001) {
- /* copy odd byte from fifo */
- tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
- *pbuffer = ntohs(tempword);
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /*
- * Check if pseudo header checksum is good
- * Calculate pseudo header checksum
- */
- tempword = *ppseudohdr++;
- for (i = 1; i < 7; i++)
- tempword ^= *ppseudohdr++;
- if (tempword != *ppseudohdr) {
- pr_debug("Pseudo header checksum mismatch\n");
- /* Drop this message */
- return false;
- }
- return true;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_proc_drvmsg
- Description: This function will process the various driver messages.
- Input:
- dev - device structure
- pnxtph - pointer to next pseudo header
- Output:
- none
-
- -------------------------------------------------------------------------*/
-static void ft1000_proc_drvmsg(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 msgtype;
- u16 tempword;
- struct media_msg *pmediamsg;
- struct dsp_init_msg *pdspinitmsg;
- struct drv_msg *pdrvmsg;
- u16 len;
- u16 i;
- struct prov_record *ptr;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- struct timeval tv;
- union {
- u8 byte[2];
- u16 wrd;
- } convert;
-
- if (info->AsicID == ELECTRABUZZ_ID)
- tempword = FT1000_DPRAM_RX_BASE+2;
- else
- tempword = FT1000_DPRAM_MAG_RX_BASE;
-
- if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) {
-
- /*
- * Get the message type which is total_len + PSEUDO header
- * + msgtype + message body
- */
- pdrvmsg = (struct drv_msg *)&cmdbuffer[0];
- msgtype = ntohs(pdrvmsg->type);
- pr_debug("Command message type = 0x%x\n", msgtype);
- switch (msgtype) {
- case DSP_PROVISION:
- pr_debug("Got a provisioning request message from DSP\n");
- mdelay(25);
- while (list_empty(&info->prov_list) == 0) {
- pr_debug("Sending a provisioning message\n");
- /* Make sure SLOWQ doorbell is clear */
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- i = 0;
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(5);
- i++;
- if (i == 10)
- break;
- }
- ptr = list_entry(info->prov_list.next,
- struct prov_record, list);
- len = *(u16 *)ptr->pprov_data;
- len = htons(len);
-
- pmsg = (u16 *)ptr->pprov_data;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- pr_debug("checksum = 0x%x\n",
- ppseudo_hdr->checksum);
- for (i = 1; i < 7; i++) {
- ppseudo_hdr->checksum ^= *pmsg++;
- pr_debug("checksum = 0x%x\n",
- ppseudo_hdr->checksum);
- }
-
- ft1000_send_cmd(dev, (u16 *)ptr->pprov_data,
- len, SLOWQ_TYPE);
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
- /*
- * Indicate adapter is ready to take application
- * messages after all provisioning messages are sent
- */
- info->CardReady = 1;
- break;
- case MEDIA_STATE:
- pmediamsg = (struct media_msg *)&cmdbuffer[0];
- if (info->ProgConStat != 0xFF) {
- if (pmediamsg->state) {
- pr_debug("Media is up\n");
- if (info->mediastate == 0) {
- netif_carrier_on(dev);
- netif_wake_queue(dev);
- info->mediastate = 1;
- do_gettimeofday(&tv);
- info->ConTm = tv.tv_sec;
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- info->ConTm = 0;
- }
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- info->ConTm = 0;
- }
- }
- break;
- case DSP_INIT_MSG:
- pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[0];
- memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
- pr_debug("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
- info->DspVer[0], info->DspVer[1],
- info->DspVer[2], info->DspVer[3]);
- memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
- HWSERNUMSZ);
- memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
- memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
- dev->dev_addr[0] = info->eui64[0];
- dev->dev_addr[1] = info->eui64[1];
- dev->dev_addr[2] = info->eui64[2];
- dev->dev_addr[3] = info->eui64[5];
- dev->dev_addr[4] = info->eui64[6];
- dev->dev_addr[5] = info->eui64[7];
-
- if (ntohs(pdspinitmsg->length) ==
- (sizeof(struct dsp_init_msg) - 20)) {
- memcpy(info->ProductMode,
- pdspinitmsg->ProductMode, MODESZ);
- memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
- CALVERSZ);
- memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
- CALDATESZ);
- pr_debug("RFCalVer = 0x%2x 0x%2x\n",
- info->RfCalVer[0], info->RfCalVer[1]);
- }
-
- break;
- case DSP_STORE_INFO:
- pr_debug("Got DSP_STORE_INFO\n");
- tempword = ntohs(pdrvmsg->length);
- info->DSPInfoBlklen = tempword;
- if (tempword < (MAX_DSP_SESS_REC - 4)) {
- pmsg = (u16 *)&pdrvmsg->data[0];
- for (i = 0; i < ((tempword + 1) / 2); i++) {
- pr_debug("dsp info data = 0x%x\n",
- *pmsg);
- info->DSPInfoBlk[i + 10] = *pmsg++;
- }
- }
- break;
- case DSP_GET_INFO:
- pr_debug("Got DSP_GET_INFO\n");
- /*
- * copy dsp info block to dsp
- * allow any outstanding ioctl to finish
- */
- mdelay(10);
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
-
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /*
- * Put message into Slow Queue
- * Form Pseudo header
- */
- pmsg = (u16 *)info->DSPInfoBlk;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length =
- htons(info->DSPInfoBlklen + 4);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- info->DSPInfoBlk[8] = 0x7200;
- info->DSPInfoBlk[9] =
- htons(info->DSPInfoBlklen);
- ft1000_send_cmd(dev, info->DSPInfoBlk,
- (u16)(info->DSPInfoBlklen+4),
- 0);
- }
-
- break;
- case GET_DRV_ERR_RPT_MSG:
- pr_debug("Got GET_DRV_ERR_RPT_MSG\n");
- /*
- * copy driver error message to dsp
- * allow any outstanding ioctl to finish
- */
- mdelay(10);
- tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
-
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /*
- * Put message into Slow Queue
- * Form Pseudo header
- */
- pmsg = (u16 *)&tempbuffer[0];
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length = htons(0x0012);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- pmsg = (u16 *)&tempbuffer[16];
- *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
- *pmsg++ = htons(0x000e);
- *pmsg++ = htons(info->DSP_TIME[0]);
- *pmsg++ = htons(info->DSP_TIME[1]);
- *pmsg++ = htons(info->DSP_TIME[2]);
- *pmsg++ = htons(info->DSP_TIME[3]);
- convert.byte[0] = info->DspVer[0];
- convert.byte[1] = info->DspVer[1];
- *pmsg++ = convert.wrd;
- convert.byte[0] = info->DspVer[2];
- convert.byte[1] = info->DspVer[3];
- *pmsg++ = convert.wrd;
- *pmsg++ = htons(info->DrvErrNum);
-
- ft1000_send_cmd(dev, (u16 *)&tempbuffer[0],
- (u16)(0x0012), 0);
- info->DrvErrNum = 0;
- }
-
- break;
- default:
- break;
- }
- }
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_parse_dpram_msg
- Description: This function will parse the message received from the DSP
- via the DPRAM interface.
- Input:
- dev - device structure
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_parse_dpram_msg(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u16 doorbell;
- u16 portid;
- u16 nxtph;
- u16 total_len;
- int i = 0;
- unsigned long flags;
-
- doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
- pr_debug("Doorbell = 0x%x\n", doorbell);
-
- if (doorbell & FT1000_ASIC_RESET_REQ) {
- /* Copy DSP session record from info block */
- spin_lock_irqsave(&info->dpram_lock, flags);
- if (info->AsicID == ELECTRABUZZ_ID) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC; i++) {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA,
- info->DSPSess.Rec[i]);
- }
- } else {
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
- FT1000_DPRAM_MAG_RX_BASE);
- for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
- outl(info->DSPSess.MagRec[i],
- dev->base_addr + FT1000_REG_MAG_DPDATA);
- }
- }
- spin_unlock_irqrestore(&info->dpram_lock, flags);
-
- /* clear ASIC RESET request */
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_ASIC_RESET_REQ);
- pr_debug("Got an ASIC RESET Request\n");
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_ASIC_RESET_DSP);
-
- if (info->AsicID == MAGNEMITE_ID) {
- /* Setting MAGNEMITE ASIC to big endian mode */
- ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
- HOST_INTF_BE);
- }
- }
-
- if (doorbell & FT1000_DSP_ASIC_RESET) {
- pr_debug("Got a dsp ASIC reset message\n");
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_DSP_ASIC_RESET);
- udelay(200);
- return SUCCESS;
- }
-
- if (doorbell & FT1000_DB_DPRAM_RX) {
- pr_debug("Got a slow queue message\n");
- nxtph = FT1000_DPRAM_RX_BASE + 2;
- if (info->AsicID == ELECTRABUZZ_ID) {
- total_len =
- ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE);
- } else {
- total_len =
- ntohs(ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_TOTAL_LEN,
- FT1000_MAG_TOTAL_LEN_INDX));
- }
- pr_debug("total length = %d\n", total_len);
- if ((total_len < MAX_CMD_SQSIZE)
- && (total_len > sizeof(struct pseudo_hdr))) {
- total_len += nxtph;
- /*
- * ft1000_read_reg will return a value that needs to be
- * byteswap in order to get DSP_QID_OFFSET.
- */
- if (info->AsicID == ELECTRABUZZ_ID) {
- portid = (ft1000_read_dpram(dev, DSP_QID_OFFSET
- + FT1000_DPRAM_RX_BASE + 2)
- >> 8) & 0xff;
- } else {
- portid =
- ft1000_read_dpram_mag_16
- (dev, FT1000_MAG_PORT_ID,
- FT1000_MAG_PORT_ID_INDX) & 0xff;
- }
- pr_debug("DSP_QID = 0x%x\n", portid);
-
- if (portid == DRIVERID) {
- /*
- * We are assumming one driver message from the
- * DSP at a time.
- */
- ft1000_proc_drvmsg(dev);
- }
- }
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX);
- }
-
- if (doorbell & FT1000_DB_COND_RESET) {
- /* Reset ASIC and DSP */
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DSP_CONDRESET_INFO;
- pr_debug("DSP conditional reset requested\n");
- ft1000_reset_card(dev);
- ft1000_write_reg(dev, FT1000_REG_DOORBELL,
- FT1000_DB_COND_RESET);
- }
- /* let's clear any unexpected doorbells from DSP */
- doorbell =
- doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ |
- FT1000_DB_COND_RESET | 0xff00);
- if (doorbell) {
- pr_debug("Clearing unexpected doorbell = 0x%x\n", doorbell);
- ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell);
- }
-
- return SUCCESS;
-
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_flush_fifo
- Description: This function will flush one packet from the downlink
- FIFO.
- Input:
- dev - device structure
- drv_err - driver error causing the flush fifo
- Output:
- None.
-
- -------------------------------------------------------------------------*/
-static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- u16 i;
- u32 templong;
- u16 tempword;
-
- if (pcmcia->PktIntfErr > MAX_PH_ERR) {
- ft1000_read_dsp_timer(dev, info);
- info->DrvErrNum = DrvErrNum;
- ft1000_reset_card(dev);
- return;
- }
- /* Flush corrupted pkt from FIFO */
- i = 0;
- do {
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DFIFO);
- tempword =
- ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
- } else {
- templong =
- inl(dev->base_addr + FT1000_REG_MAG_DFR);
- tempword =
- inw(dev->base_addr + FT1000_REG_MAG_DFSR);
- }
- i++;
- /*
- * This should never happen unless the ASIC is broken.
- * We must reset to recover.
- */
- if ((i > 2048) || (tempword == 0)) {
- ft1000_read_dsp_timer(dev, info);
- if (tempword == 0) {
- /*
- * Let's check if ASIC reads are still ok by
- * reading the Mask register which is never zero
- * at this point of the code.
- */
- tempword =
- inw(dev->base_addr +
- FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- /*
- * This indicates that we can not
- * communicate with the ASIC
- */
- info->DrvErrNum = FIFO_FLUSH_BADCNT;
- } else {
- /*
- * Let's assume that we really flush
- * the FIFO
- */
- pcmcia->PktIntfErr++;
- return;
- }
- } else {
- info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
- }
- return;
- }
- tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
- } while ((tempword & 0x03) != 0x03);
- if (info->AsicID == ELECTRABUZZ_ID) {
- i++;
- pr_debug("Flushing FIFO complete = %x\n", tempword);
- /* Flush last word in FIFO. */
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- /* Update FIFO counter for DSP */
- i = i * 2;
- pr_debug("Flush Data byte count to dsp = %d\n", i);
- info->fifo_cnt += i;
- ft1000_write_dpram(dev, FT1000_FIFO_LEN,
- info->fifo_cnt);
- } else {
- pr_debug("Flushing FIFO complete = %x\n", tempword);
- /* Flush last word in FIFO */
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
- pr_debug("FT1000_REG_SUP_STAT = 0x%x\n", tempword);
- tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
- pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
- }
- if (DrvErrNum)
- pcmcia->PktIntfErr++;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_copy_up_pkt
- Description: This function will pull Flarion packets out of the Downlink
- FIFO and convert it to an ethernet packet. The ethernet packet will
- then be deliver to the TCP/IP stack.
- Input:
- dev - device structure
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_copy_up_pkt(struct net_device *dev)
-{
- u16 tempword;
- struct ft1000_info *info = netdev_priv(dev);
- u16 len;
- struct sk_buff *skb;
- u16 i;
- u8 *pbuffer = NULL;
- u8 *ptemp = NULL;
- u16 chksum;
- u32 *ptemplong;
- u32 templong;
-
- /* Read length */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- len = tempword;
- } else {
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- len = ntohs(tempword);
- }
- chksum = tempword;
- pr_debug("Number of Bytes in FIFO = %d\n", len);
-
- if (len > ENET_MAX_SIZE) {
- pr_debug("size of ethernet packet invalid\n");
- if (info->AsicID == MAGNEMITE_ID) {
- /* Read High word to complete 32 bit access */
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- }
- ft1000_flush_fifo(dev, DSP_PKTLEN_INFO);
- info->stats.rx_errors++;
- return FAILURE;
- }
-
- skb = dev_alloc_skb(len + 12 + 2);
-
- if (skb == NULL) {
- /* Read High word to complete 32 bit access */
- if (info->AsicID == MAGNEMITE_ID)
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
-
- ft1000_flush_fifo(dev, 0);
- info->stats.rx_errors++;
- return FAILURE;
- }
- pbuffer = (u8 *)skb_put(skb, len + 12);
-
- /* Pseudo header */
- if (info->AsicID == ELECTRABUZZ_ID) {
- for (i = 1; i < 7; i++) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- chksum ^= tempword;
- }
- /* read checksum value */
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- } else {
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
- pr_debug("Pseudo = 0x%x\n", tempword);
- chksum ^= tempword;
-
- /* read checksum value */
- tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
- pr_debug("Pseudo = 0x%x\n", tempword);
- }
-
- if (chksum != tempword) {
- pr_debug("Packet checksum mismatch 0x%x 0x%x\n",
- chksum, tempword);
- ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO);
- info->stats.rx_errors++;
- kfree_skb(skb);
- return FAILURE;
- }
- /* subtract the number of bytes read already */
- ptemp = pbuffer;
-
- /* fake MAC address */
- *pbuffer++ = dev->dev_addr[0];
- *pbuffer++ = dev->dev_addr[1];
- *pbuffer++ = dev->dev_addr[2];
- *pbuffer++ = dev->dev_addr[3];
- *pbuffer++ = dev->dev_addr[4];
- *pbuffer++ = dev->dev_addr[5];
- *pbuffer++ = 0x00;
- *pbuffer++ = 0x07;
- *pbuffer++ = 0x35;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xfe;
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- for (i = 0; i < len / 2; i++) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- *pbuffer++ = (u8) (tempword >> 8);
- *pbuffer++ = (u8)tempword;
- if (ft1000_chkcard(dev) == false) {
- kfree_skb(skb);
- return FAILURE;
- }
- }
-
- /* Need to read one more word if odd byte */
- if (len & 0x0001) {
- tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
- *pbuffer++ = (u8) (tempword >> 8);
- }
- } else {
- ptemplong = (u32 *)pbuffer;
- for (i = 0; i < len / 4; i++) {
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- pr_debug("Data = 0x%8x\n", templong);
- *ptemplong++ = templong;
- }
-
- /* Need to read one more word if odd align. */
- if (len & 0x0003) {
- templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
- pr_debug("Data = 0x%8x\n", templong);
- *ptemplong++ = templong;
- }
-
- }
-
- pr_debug("Data passed to Protocol layer:\n");
- for (i = 0; i < len + 12; i++)
- pr_debug("Protocol Data: 0x%x\n", *ptemp++);
-
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
-
- info->stats.rx_packets++;
- /* Add on 12 bytes for MAC address which was removed */
- info->stats.rx_bytes += (len + 12);
-
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* track how many bytes have been read from FIFO - round up to
- * 16 bit word */
- tempword = len + 16;
- if (tempword & 0x01)
- tempword++;
- info->fifo_cnt += tempword;
- ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN);
- ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt);
- }
-
- return SUCCESS;
-}
-
-/*---------------------------------------------------------------------------
-
- Function: ft1000_copy_down_pkt
- Description: This function will take an ethernet packet and convert it to
- a Flarion packet prior to sending it to the ASIC Downlink
- FIFO.
- Input:
- dev - device structure
- packet - address of ethernet packet
- len - length of IP packet
- Output:
- status - FAILURE
- SUCCESS
-
- -------------------------------------------------------------------------*/
-static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_pcmcia *pcmcia = info->priv;
- union {
- struct pseudo_hdr blk;
- u16 buff[sizeof(struct pseudo_hdr) >> 1];
- u8 buffc[sizeof(struct pseudo_hdr)];
- } pseudo;
- int i;
- u32 *plong;
-
- /* Check if there is room on the FIFO */
- if (len > ft1000_read_fifo_len(dev)) {
- udelay(10);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev))
- udelay(20);
- if (len > ft1000_read_fifo_len(dev)) {
- pr_debug("Transmit FIFO is full - pkt drop\n");
- info->stats.tx_errors++;
- return SUCCESS;
- }
- }
- /* Create pseudo header and send pseudo/ip to hardware */
- if (info->AsicID == ELECTRABUZZ_ID)
- pseudo.blk.length = len;
- else
- pseudo.blk.length = ntohs(len);
-
- pseudo.blk.source = DSPID; /* Need to swap to get in correct
- order */
- pseudo.blk.destination = HOSTID;
- pseudo.blk.portdest = NETWORKID; /* Need to swap to get in
- correct order */
- pseudo.blk.portsrc = DSPAIRID;
- pseudo.blk.sh_str_id = 0;
- pseudo.blk.control = 0;
- pseudo.blk.rsvd1 = 0;
- pseudo.blk.seq_num = 0;
- pseudo.blk.rsvd2 = pcmcia->packetseqnum++;
- pseudo.blk.qos_class = 0;
- /* Calculate pseudo header checksum */
- pseudo.blk.checksum = pseudo.buff[0];
- for (i = 1; i < 7; i++)
- pseudo.blk.checksum ^= pseudo.buff[i];
-
- /* Production Mode */
- if (info->AsicID == ELECTRABUZZ_ID) {
- /* copy first word to UFIFO_BEG reg */
- ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]);
- pr_debug("data 0 BEG = 0x%04x\n", pseudo.buff[0]);
-
- /* copy subsequent words to UFIFO_MID reg */
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]);
- pr_debug("data 1 MID = 0x%04x\n", pseudo.buff[1]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]);
- pr_debug("data 2 MID = 0x%04x\n", pseudo.buff[2]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]);
- pr_debug("data 3 MID = 0x%04x\n", pseudo.buff[3]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]);
- pr_debug("data 4 MID = 0x%04x\n", pseudo.buff[4]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]);
- pr_debug("data 5 MID = 0x%04x\n", pseudo.buff[5]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]);
- pr_debug("data 6 MID = 0x%04x\n", pseudo.buff[6]);
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]);
- pr_debug("data 7 MID = 0x%04x\n", pseudo.buff[7]);
-
- /* Write PPP type + IP Packet into Downlink FIFO */
- for (i = 0; i < (len >> 1) - 1; i++) {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- packet++;
- }
-
- /* Check for odd byte */
- if (len & 0x0001) {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
- htons(*packet));
- pr_debug("data MID = 0x%04x\n", htons(*packet));
- packet++;
- ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- } else {
- ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
- htons(*packet));
- pr_debug("data %d MID = 0x%04x\n",
- i + 8, htons(*packet));
- }
- } else {
- outl(*(u32 *)&pseudo.buff[0],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[0]);
- outl(*(u32 *)&pseudo.buff[2],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[2]);
- outl(*(u32 *)&pseudo.buff[4],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[4]);
- outl(*(u32 *)&pseudo.buff[6],
- dev->base_addr + FT1000_REG_MAG_UFDR);
- pr_debug("Pseudo = 0x%8x\n", *(u32 *)&pseudo.buff[6]);
-
- plong = (u32 *)packet;
- /* Write PPP type + IP Packet into Downlink FIFO */
- for (i = 0; i < (len >> 2); i++)
- outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
-
- /* Check for odd alignment */
- if (len & 0x0003) {
- pr_debug("data = 0x%8x\n", *plong);
- outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
- }
- outl(1, dev->base_addr + FT1000_REG_MAG_UFER);
- }
-
- info->stats.tx_packets++;
- /* Add 14 bytes for MAC address plus ethernet type */
- info->stats.tx_bytes += (len + 14);
- return SUCCESS;
-}
-
-static struct net_device_stats *ft1000_stats(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- return &info->stats;
-}
-
-static int ft1000_open(struct net_device *dev)
-{
- ft1000_reset_card(dev);
-
- /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP
- * and ASIC */
- init_timer(&poll_timer);
- poll_timer.expires = jiffies + (2 * HZ);
- poll_timer.data = (u_long)dev;
- add_timer(&poll_timer);
-
- return 0;
-}
-
-static int ft1000_close(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- info->CardReady = 0;
- del_timer(&poll_timer);
-
- if (ft1000_card_present == 1) {
- pr_debug("Media is down\n");
- netif_stop_queue(dev);
-
- ft1000_disable_interrupts(dev);
- ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
-
- /* reset ASIC */
- ft1000_reset_asic(dev);
- }
- return 0;
-}
-
-static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- u8 *pdata;
-
- if (skb == NULL) {
- pr_debug("skb == NULL!!!\n");
- return 0;
- }
-
- pr_debug("length of packet = %d\n", skb->len);
-
- pdata = (u8 *)skb->data;
-
- if (info->mediastate == 0) {
- /* Drop packet is mediastate is down */
- pr_debug("mediastate is down\n");
- return SUCCESS;
- }
-
- if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
- /* Drop packet which has invalid size */
- pr_debug("invalid ethernet length\n");
- return SUCCESS;
- }
- ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2),
- skb->len - ENET_HEADER_SIZE + 2);
-
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct ft1000_info *info = netdev_priv(dev);
- u16 tempword;
- u16 inttype;
- int cnt;
-
- if (info->CardReady == 0) {
- ft1000_disable_interrupts(dev);
- return IRQ_HANDLED;
- }
-
- if (ft1000_chkcard(dev) == false) {
- ft1000_disable_interrupts(dev);
- return IRQ_HANDLED;
- }
-
- ft1000_disable_interrupts(dev);
-
- /* Read interrupt type */
- inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
-
- /* Make sure we process all interrupt before leaving the ISR due to the
- * edge trigger interrupt type */
- while (inttype) {
- if (inttype & ISR_DOORBELL_PEND)
- ft1000_parse_dpram_msg(dev);
-
- if (inttype & ISR_RCV) {
- pr_debug("Data in FIFO\n");
-
- cnt = 0;
- do {
- /* Check if we have packets in the Downlink
- * FIFO */
- if (info->AsicID == ELECTRABUZZ_ID) {
- tempword = ft1000_read_reg(dev,
- FT1000_REG_DFIFO_STAT);
- } else {
- tempword = ft1000_read_reg(dev,
- FT1000_REG_MAG_DFSR);
- }
- if (!(tempword & 0x1f))
- break;
- ft1000_copy_up_pkt(dev);
- cnt++;
- } while (cnt < MAX_RCV_LOOP);
-
- }
- /* clear interrupts */
- tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
-
- /* Read interrupt type */
- inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register after clear = 0x%x\n",
- inttype);
- }
- ft1000_enable_interrupts(dev);
- return IRQ_HANDLED;
-}
-
-void stop_ft1000_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct prov_record *ptr;
- struct prov_record *tmp;
- /* int cnt; */
-
- info->CardReady = 0;
- ft1000_card_present = 0;
- netif_stop_queue(dev);
- ft1000_disable_interrupts(dev);
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- kfree(info->priv);
-
- if (info->registered) {
- unregister_netdev(dev);
- info->registered = 0;
- }
-
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, 256);
- release_firmware(fw_entry);
- flarion_ft1000_cnt--;
-
-}
-
-static void ft1000_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct ft1000_info *ft_info;
-
- ft_info = netdev_priv(dev);
-
- strlcpy(info->driver, "ft1000", sizeof(info->driver));
- snprintf(info->bus_info, sizeof(info->bus_info), "PCMCIA 0x%lx",
- dev->base_addr);
- snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d.%d",
- ft_info->DspVer[0], ft_info->DspVer[1], ft_info->DspVer[2],
- ft_info->DspVer[3]);
-}
-
-static u32 ft1000_get_link(struct net_device *dev)
-{
- struct ft1000_info *info;
-
- info = netdev_priv(dev);
- return info->mediastate;
-}
-
-static const struct ethtool_ops ops = {
- .get_drvinfo = ft1000_get_drvinfo,
- .get_link = ft1000_get_link
-};
-
-struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset)
-{
- struct ft1000_info *info;
- struct ft1000_pcmcia *pcmcia;
- struct net_device *dev;
-
- static const struct net_device_ops ft1000ops = {
- .ndo_open = &ft1000_open,
- .ndo_stop = &ft1000_close,
- .ndo_start_xmit = &ft1000_start_xmit,
- .ndo_get_stats = &ft1000_stats,
- };
-
- pr_debug("irq = %d, port = 0x%04llx\n",
- link->irq, (unsigned long long)link->resource[0]->start);
-
- flarion_ft1000_cnt++;
-
- if (flarion_ft1000_cnt > 1) {
- flarion_ft1000_cnt--;
-
- dev_info(&link->dev,
- "This driver can not support more than one instance\n");
- return NULL;
- }
-
- dev = alloc_etherdev(sizeof(struct ft1000_info));
- if (!dev) {
- dev_err(&link->dev, "Failed to allocate etherdev\n");
- return NULL;
- }
-
- SET_NETDEV_DEV(dev, &link->dev);
- info = netdev_priv(dev);
-
- memset(info, 0, sizeof(struct ft1000_info));
-
- pr_debug("address of dev = 0x%p\n", dev);
- pr_debug("address of dev info = 0x%p\n", info);
- pr_debug("device name = %s\n", dev->name);
-
- memset(&info->stats, 0, sizeof(struct net_device_stats));
-
- info->priv = kzalloc(sizeof(struct ft1000_pcmcia), GFP_KERNEL);
- pcmcia = info->priv;
- pcmcia->link = link;
-
- spin_lock_init(&info->dpram_lock);
- info->DrvErrNum = 0;
- info->registered = 1;
- info->ft1000_reset = ft1000_reset;
- info->mediastate = 0;
- info->fifo_cnt = 0;
- info->CardReady = 0;
- info->DSP_TIME[0] = 0;
- info->DSP_TIME[1] = 0;
- info->DSP_TIME[2] = 0;
- info->DSP_TIME[3] = 0;
- flarion_ft1000_cnt = 0;
-
- INIT_LIST_HEAD(&info->prov_list);
-
- info->squeseqnum = 0;
-
- /* dev->hard_start_xmit = &ft1000_start_xmit; */
- /* dev->get_stats = &ft1000_stats; */
- /* dev->open = &ft1000_open; */
- /* dev->stop = &ft1000_close; */
-
- dev->netdev_ops = &ft1000ops;
-
- pr_debug("device name = %s\n", dev->name);
-
- dev->irq = link->irq;
- dev->base_addr = link->resource[0]->start;
- if (pcmcia_get_mac_from_cis(link, dev)) {
- netdev_err(dev, "Could not read mac address\n");
- goto err_dev;
- }
-
- if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name,
- dev)) {
- netdev_err(dev, "Could not request_irq\n");
- goto err_dev;
- }
-
- if (request_region(dev->base_addr, 256, dev->name) == NULL) {
- netdev_err(dev, "Could not request_region\n");
- goto err_irq;
- }
-
- if (register_netdev(dev)) {
- pr_debug("Could not register netdev\n");
- goto err_reg;
- }
-
- info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
- if (info->AsicID == ELECTRABUZZ_ID) {
- pr_debug("ELECTRABUZZ ASIC\n");
- if (request_firmware(&fw_entry, "ft1000.img",
- &link->dev) != 0) {
- pr_info("Could not open ft1000.img\n");
- goto err_unreg;
- }
- } else {
- pr_debug("MAGNEMITE ASIC\n");
- if (request_firmware(&fw_entry, "ft2000.img",
- &link->dev) != 0) {
- pr_info("Could not open ft2000.img\n");
- goto err_unreg;
- }
- }
-
- ft1000_enable_interrupts(dev);
-
- ft1000_card_present = 1;
- dev->ethtool_ops = &ops;
- pr_info("%s: addr 0x%04lx irq %d, MAC addr %pM\n",
- dev->name, dev->base_addr, dev->irq, dev->dev_addr);
- return dev;
-
-err_unreg:
- unregister_netdev(dev);
-err_reg:
- release_region(dev->base_addr, 256);
-err_irq:
- free_irq(dev->irq, dev);
-err_dev:
- free_netdev(dev);
- return NULL;
-}
+++ /dev/null
-obj-$(CONFIG_FT1000_USB) += ft1000.o
-
-ft1000-y := ft1000_debug.o ft1000_download.o ft1000_hw.o ft1000_usb.o
+++ /dev/null
-/*
- *---------------------------------------------------------------------------
- * FT1000 driver for Flarion Flash OFDM NIC Device
- *
- * Copyright (C) 2006 Flarion Technologies, All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) any
- * later version. This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details. You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place -
- * Suite 330, Boston, MA 02111-1307, USA.
- *---------------------------------------------------------------------------
- *
- * File: ft1000_chdev.c
- *
- * Description: Custom character device dispatch routines.
- *
- * History:
- * 8/29/02 Whc Ported to Linux.
- * 6/05/06 Whc Porting to Linux 2.6.9
- *
- *---------------------------------------------------------------------------
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include <linux/ioctl.h>
-#include <linux/debugfs.h>
-#include "ft1000_usb.h"
-
-static int ft1000_flarion_cnt;
-
-static int ft1000_open(struct inode *inode, struct file *file);
-static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait);
-static long ft1000_ioctl(struct file *file, unsigned int command,
- unsigned long argument);
-static int ft1000_release(struct inode *inode, struct file *file);
-
-/* List to free receive command buffer pool */
-struct list_head freercvpool;
-
-/* lock to arbitrate free buffer list for receive command data */
-spinlock_t free_buff_lock;
-
-int numofmsgbuf;
-
-/*
- * Table of entry-point routines for char device
- */
-static const struct file_operations ft1000fops = {
- .unlocked_ioctl = ft1000_ioctl,
- .poll = ft1000_poll_dev,
- .open = ft1000_open,
- .release = ft1000_release,
- .llseek = no_llseek,
-};
-
-/*
- ---------------------------------------------------------------------------
- * Function: ft1000_get_buffer
- *
- * Parameters:
- *
- * Returns:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
-{
- unsigned long flags;
- struct dpram_blk *ptr;
-
- spin_lock_irqsave(&free_buff_lock, flags);
- /* Check if buffer is available */
- if (list_empty(bufflist)) {
- pr_debug("No more buffer - %d\n", numofmsgbuf);
- ptr = NULL;
- } else {
- numofmsgbuf--;
- ptr = list_entry(bufflist->next, struct dpram_blk, list);
- list_del(&ptr->list);
- /* pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
- }
- spin_unlock_irqrestore(&free_buff_lock, flags);
-
- return ptr;
-}
-
-
-
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_free_buffer
- *
- * Parameters:
- *
- * Returns:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&free_buff_lock, flags);
- /* Put memory back to list */
- list_add_tail(&pdpram_blk->list, plist);
- numofmsgbuf++;
- /*pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
- spin_unlock_irqrestore(&free_buff_lock, flags);
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_CreateDevice
- *
- * Parameters: dev - pointer to adapter object
- *
- * Returns: 0 if successful
- *
- * Description: Creates a private char device.
- *
- * Notes: Only called by init_module().
- *
- *---------------------------------------------------------------------------
- */
-int ft1000_create_dev(struct ft1000_usb *dev)
-{
- int result;
- int i;
- struct dentry *dir, *file;
- struct ft1000_debug_dirs *tmp;
-
- /* make a new device name */
- sprintf(dev->DeviceName, "%s%d", "FT1000_", dev->CardNumber);
-
- pr_debug("number of instance = %d\n", ft1000_flarion_cnt);
- pr_debug("DeviceCreated = %x\n", dev->DeviceCreated);
-
- if (dev->DeviceCreated) {
- pr_debug("\"%s\" already registered\n", dev->DeviceName);
- return -EIO;
- }
-
-
- /* register the device */
- pr_debug("\"%s\" debugfs device registration\n", dev->DeviceName);
-
- tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
- if (tmp == NULL) {
- result = -1;
- goto fail;
- }
-
- dir = debugfs_create_dir(dev->DeviceName, NULL);
- if (IS_ERR(dir)) {
- result = PTR_ERR(dir);
- goto debug_dir_fail;
- }
-
- file = debugfs_create_file("device", S_IRUGO | S_IWUSR, dir,
- dev, &ft1000fops);
- if (IS_ERR(file)) {
- result = PTR_ERR(file);
- goto debug_file_fail;
- }
-
- tmp->dent = dir;
- tmp->file = file;
- tmp->int_number = dev->CardNumber;
- list_add(&tmp->list, &dev->nodes.list);
-
- pr_debug("registered debugfs directory \"%s\"\n", dev->DeviceName);
-
- /* initialize application information */
- dev->appcnt = 0;
- for (i = 0; i < MAX_NUM_APP; i++) {
- dev->app_info[i].nTxMsg = 0;
- dev->app_info[i].nRxMsg = 0;
- dev->app_info[i].nTxMsgReject = 0;
- dev->app_info[i].nRxMsgMiss = 0;
- dev->app_info[i].fileobject = NULL;
- dev->app_info[i].app_id = i+1;
- dev->app_info[i].DspBCMsgFlag = 0;
- dev->app_info[i].NumOfMsg = 0;
- init_waitqueue_head(&dev->app_info[i].wait_dpram_msg);
- INIT_LIST_HEAD(&dev->app_info[i].app_sqlist);
- }
-
- dev->DeviceCreated = TRUE;
- ft1000_flarion_cnt++;
-
- return 0;
-
-debug_file_fail:
- debugfs_remove(dir);
-debug_dir_fail:
- kfree(tmp);
-fail:
- return result;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_DestroyDeviceDEBUG
- *
- * Parameters: dev - pointer to adapter object
- *
- * Description: Destroys a private char device.
- *
- * Notes: Only called by cleanup_module().
- *
- *---------------------------------------------------------------------------
- */
-void ft1000_destroy_dev(struct net_device *netdev)
-{
- struct ft1000_info *info = netdev_priv(netdev);
- struct ft1000_usb *dev = info->priv;
- int i;
- struct dpram_blk *pdpram_blk;
- struct dpram_blk *ptr;
- struct list_head *pos, *q;
- struct ft1000_debug_dirs *dir;
-
- if (dev->DeviceCreated) {
- ft1000_flarion_cnt--;
- list_for_each_safe(pos, q, &dev->nodes.list) {
- dir = list_entry(pos, struct ft1000_debug_dirs, list);
- if (dir->int_number == dev->CardNumber) {
- debugfs_remove(dir->file);
- debugfs_remove(dir->dent);
- list_del(pos);
- kfree(dir);
- }
- }
- pr_debug("unregistered device \"%s\"\n", dev->DeviceName);
-
- /* Make sure we free any memory reserve for slow Queue */
- for (i = 0; i < MAX_NUM_APP; i++) {
- while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
- pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next,
- struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- ft1000_free_buffer(pdpram_blk, &freercvpool);
-
- }
- wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
- }
-
- /* Remove buffer allocated for receive command data */
- if (ft1000_flarion_cnt == 0) {
- while (list_empty(&freercvpool) == 0) {
- ptr = list_entry(freercvpool.next, struct dpram_blk, list);
- list_del(&ptr->list);
- kfree(ptr->pbuffer);
- kfree(ptr);
- }
- }
- dev->DeviceCreated = FALSE;
- }
-
-
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_open
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static int ft1000_open(struct inode *inode, struct file *file)
-{
- struct ft1000_info *info;
- struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
- int i, num;
-
- num = MINOR(inode->i_rdev) & 0xf;
- pr_debug("minor number=%d\n", num);
-
- info = file->private_data = netdev_priv(dev->net);
-
- pr_debug("f_owner = %p number of application = %d\n",
- &file->f_owner, dev->appcnt);
-
- /* Check if maximum number of application exceeded */
- if (dev->appcnt > MAX_NUM_APP) {
- pr_debug("Maximum number of application exceeded\n");
- return -EACCES;
- }
-
- /* Search for available application info block */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].fileobject == NULL)
- break;
- }
-
- /* Fail due to lack of application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find an application info block\n");
- return -EACCES;
- }
-
- dev->appcnt++;
- dev->app_info[i].fileobject = &file->f_owner;
- dev->app_info[i].nTxMsg = 0;
- dev->app_info[i].nRxMsg = 0;
- dev->app_info[i].nTxMsgReject = 0;
- dev->app_info[i].nRxMsgMiss = 0;
-
- nonseekable_open(inode, file);
- return 0;
-}
-
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_poll_dev
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-
-static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
-{
- struct net_device *netdev = file->private_data;
- struct ft1000_info *info = netdev_priv(netdev);
- struct ft1000_usb *dev = info->priv;
- int i;
-
- if (ft1000_flarion_cnt == 0) {
- pr_debug("called with ft1000_flarion_cnt value zero\n");
- return -EBADF;
- }
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].fileobject == &file->f_owner) {
- /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
- break;
- }
- }
-
- /* Could not find application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find application info block\n");
- return -EACCES;
- }
-
- if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
- pr_debug("Message detected in slow queue\n");
- return(POLLIN | POLLRDNORM | POLLPRI);
- }
-
- poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
- /* pr_debug("Polling for data from DSP\n"); */
-
- return 0;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_ioctl
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static long ft1000_ioctl(struct file *file, unsigned int command,
- unsigned long argument)
-{
- void __user *argp = (void __user *)argument;
- struct ft1000_info *info;
- struct ft1000_usb *ft1000dev;
- int result = 0;
- int cmd;
- int i;
- u16 tempword;
- unsigned long flags;
- struct timeval tv;
- struct IOCTL_GET_VER get_ver_data;
- struct IOCTL_GET_DSP_STAT get_stat_data;
- u8 ConnectionMsg[] = {
- 0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
- 0x00, 0x01, 0x00, 0x00
- };
-
- unsigned short ledStat = 0;
- unsigned short conStat = 0;
-
- if (ft1000_flarion_cnt == 0) {
- pr_debug("called with ft1000_flarion_cnt of zero\n");
- return -EBADF;
- }
-
- /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
-
- info = file->private_data;
- ft1000dev = info->priv;
- cmd = _IOC_NR(command);
- /* pr_debug("cmd = 0x%x\n", cmd); */
-
- /* process the command */
- switch (cmd) {
- case IOCTL_REGISTER_CMD:
- pr_debug("IOCTL_FT1000_REGISTER called\n");
- result = get_user(tempword, (__u16 __user *)argp);
- if (result) {
- pr_debug("result = %d failed to get_user\n", result);
- break;
- }
- if (tempword == DSPBCMSGID) {
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- ft1000dev->app_info[i].DspBCMsgFlag = 1;
- pr_debug("Registered for broadcast messages\n");
- break;
- }
- }
- }
- break;
-
- case IOCTL_GET_VER_CMD:
- pr_debug("IOCTL_FT1000_GET_VER called\n");
-
- get_ver_data.drv_ver = FT1000_DRV_VER;
-
- if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
-
- pr_debug("driver version = 0x%x\n",
- (unsigned int)get_ver_data.drv_ver);
-
- break;
- case IOCTL_CONNECT:
- /* Connect Message */
- pr_debug("IOCTL_FT1000_CONNECT\n");
- ConnectionMsg[79] = 0xfc;
- result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
-
- break;
- case IOCTL_DISCONNECT:
- /* Disconnect Message */
- pr_debug("IOCTL_FT1000_DISCONNECT\n");
- ConnectionMsg[79] = 0xfd;
- result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
- break;
- case IOCTL_GET_DSP_STAT_CMD:
- /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
- memset(&get_stat_data, 0, sizeof(get_stat_data));
- memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
- memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
- memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
- memcpy(get_stat_data.eui64, info->eui64, EUISZ);
-
- if (info->ProgConStat != 0xFF) {
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
- (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
- get_stat_data.LedStat = ntohs(ledStat);
- pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
- (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
- get_stat_data.ConStat = ntohs(conStat);
- pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
- } else {
- get_stat_data.ConStat = 0x0f;
- }
-
-
- get_stat_data.nTxPkts = info->stats.tx_packets;
- get_stat_data.nRxPkts = info->stats.rx_packets;
- get_stat_data.nTxBytes = info->stats.tx_bytes;
- get_stat_data.nRxBytes = info->stats.rx_bytes;
- do_gettimeofday(&tv);
- get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
- pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
- if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
- pr_debug("GET_DSP_STAT succeed\n");
- break;
- case IOCTL_SET_DPRAM_CMD:
- {
- struct IOCTL_DPRAM_BLK *dpram_data = NULL;
- /* struct IOCTL_DPRAM_COMMAND dpram_command; */
- u16 qtype;
- u16 msgsz;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- u16 total_len;
- u16 app_index;
- u16 status;
-
- /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
-
-
- if (ft1000_flarion_cnt == 0)
- return -EBADF;
-
- if (ft1000dev->DrvMsgPend)
- return -ENOTTY;
-
- if (ft1000dev->fProvComplete == 0)
- return -EACCES;
-
- ft1000dev->fAppMsgPend = true;
-
- if (info->CardReady) {
-
- /* pr_debug("try to SET_DPRAM\n"); */
-
- /* Get the length field to see how many bytes to copy */
- result = get_user(msgsz, (__u16 __user *)argp);
- if (result)
- break;
- msgsz = ntohs(msgsz);
- /* pr_debug("length of message = %d\n", msgsz); */
-
- if (msgsz > MAX_CMD_SQSIZE) {
- pr_debug("bad message length = %d\n", msgsz);
- result = -EINVAL;
- break;
- }
-
- result = -ENOMEM;
- dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
- if (!dpram_data)
- break;
-
- if (copy_from_user(dpram_data, argp, msgsz+2)) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- } else {
- /* Check if this message came from a registered application */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner)
- break;
- }
- if (i == MAX_NUM_APP) {
- pr_debug("No matching application fileobject\n");
- result = -EINVAL;
- kfree(dpram_data);
- break;
- }
- app_index = i;
-
- /* Check message qtype type which is the lower byte within qos_class */
- qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
- /* pr_debug("qtype = %d\n", qtype); */
- if (!qtype) {
- /* Put message into Slow Queue */
- /* Only put a message into the DPRAM if msg doorbell is available */
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 2ms and try again due to DSP doorbell busy */
- mdelay(2);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 1ms and try again due to DSP doorbell busy */
- mdelay(1);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- /* Suspend for 3ms and try again due to DSP doorbell busy */
- mdelay(3);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- pr_debug("Doorbell not available\n");
- result = -ENOTTY;
- kfree(dpram_data);
- break;
- }
- }
- }
- }
- }
-
- /*pr_debug("finished reading register\n"); */
-
- /* Make sure we are within the limits of the slow queue memory limitation */
- if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
- /* Need to put sequence number plus new checksum for message */
- pmsg = (u16 *)&dpram_data->pseudohdr;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- total_len = msgsz+2;
- if (total_len & 0x1)
- total_len++;
-
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
- for (i = 1; i < 7; i++) {
- ppseudo_hdr->checksum ^= *pmsg++;
- /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
- }
- pmsg++;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- result = card_send_command(ft1000dev, dpram_data, total_len+2);
-
-
- ft1000dev->app_info[app_index].nTxMsg++;
- } else {
- result = -EINVAL;
- }
- }
- }
- } else {
- pr_debug("Card not ready take messages\n");
- result = -EACCES;
- }
- kfree(dpram_data);
-
- }
- break;
- case IOCTL_GET_DPRAM_CMD:
- {
- struct dpram_blk *pdpram_blk;
- struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
- int msglen;
-
- /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
-
- if (ft1000_flarion_cnt == 0)
- return -EBADF;
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
- break;
- }
- }
-
- /* Could not find application info block */
- if (i == MAX_NUM_APP) {
- pr_debug("Could not find application info block\n");
- result = -EBADF;
- break;
- }
-
- result = 0;
- pioctl_dpram = argp;
- if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
- /* pr_debug("Message detected in slow queue\n"); */
- spin_lock_irqsave(&free_buff_lock, flags);
- pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
- struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- ft1000dev->app_info[i].NumOfMsg--;
- /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
- spin_unlock_irqrestore(&free_buff_lock, flags);
- msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
- result = get_user(msglen, &pioctl_dpram->total_len);
- if (result)
- break;
- msglen = htons(msglen);
- /* pr_debug("msg length = %x\n", msglen); */
- if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
- pr_debug("copy fault occurred\n");
- result = -EFAULT;
- break;
- }
-
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- result = msglen;
- }
- /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
- }
- break;
-
- default:
- pr_debug("unknown command: 0x%x\n", command);
- result = -ENOTTY;
- break;
- }
- ft1000dev->fAppMsgPend = false;
- return result;
-}
-
-/*
- *---------------------------------------------------------------------------
- * Function: ft1000_release
- *
- * Parameters:
- *
- * Description:
- *
- * Notes:
- *
- *---------------------------------------------------------------------------
- */
-static int ft1000_release(struct inode *inode, struct file *file)
-{
- struct ft1000_info *info;
- struct net_device *dev;
- struct ft1000_usb *ft1000dev;
- int i;
- struct dpram_blk *pdpram_blk;
- struct dpram_blk *tmp;
-
- dev = file->private_data;
- info = netdev_priv(dev);
- ft1000dev = info->priv;
-
- if (ft1000_flarion_cnt == 0) {
- ft1000dev->appcnt--;
- return -EBADF;
- }
-
- /* Search for matching file object */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
- /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
- break;
- }
- }
-
- if (i == MAX_NUM_APP)
- return 0;
-
- list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
- pr_debug("Remove and free memory queue up on slow queue\n");
- list_del(&pdpram_blk->list);
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- }
-
- /* initialize application information */
- ft1000dev->appcnt--;
- pr_debug("appcnt = %d\n", ft1000dev->appcnt);
- ft1000dev->app_info[i].fileobject = NULL;
-
- return 0;
-}
+++ /dev/null
-/*
- * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- * This file is part of Express Card USB Driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include "ft1000_usb.h"
-
-
-#define DWNLD_HANDSHAKE_LOC 0x02
-#define DWNLD_TYPE_LOC 0x04
-#define DWNLD_SIZE_MSW_LOC 0x06
-#define DWNLD_SIZE_LSW_LOC 0x08
-#define DWNLD_PS_HDR_LOC 0x0A
-
-#define MAX_DSP_WAIT_LOOPS 40
-#define DSP_WAIT_SLEEP_TIME 1000 /* 1 millisecond */
-#define DSP_WAIT_DISPATCH_LVL 50 /* 50 usec */
-
-#define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
-#define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
-#define HANDSHAKE_RESET_VALUE_USB 0xFE7E /* When DSP requests startover */
-#define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DSP_BL_READY_USB 0xFE7E /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
-#define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
-
-#define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
-#define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
-
-#define REQUEST_CODE_LENGTH 0x0000
-#define REQUEST_RUN_ADDRESS 0x0001
-#define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
-#define REQUEST_DONE_BL 0x0003
-#define REQUEST_DONE_CL 0x0004
-#define REQUEST_VERSION_INFO 0x0005
-#define REQUEST_CODE_BY_VERSION 0x0006
-#define REQUEST_MAILBOX_DATA 0x0007
-#define REQUEST_FILE_CHECKSUM 0x0008
-
-#define STATE_START_DWNLD 0x01
-#define STATE_BOOT_DWNLD 0x02
-#define STATE_CODE_DWNLD 0x03
-#define STATE_DONE_DWNLD 0x04
-#define STATE_SECTION_PROV 0x05
-#define STATE_DONE_PROV 0x06
-#define STATE_DONE_FILE 0x07
-
-#define MAX_LENGTH 0x7f0
-
-/* Temporary download mechanism for Magnemite */
-#define DWNLD_MAG_TYPE_LOC 0x00
-#define DWNLD_MAG_LEN_LOC 0x01
-#define DWNLD_MAG_ADDR_LOC 0x02
-#define DWNLD_MAG_CHKSUM_LOC 0x03
-#define DWNLD_MAG_VAL_LOC 0x04
-
-#define HANDSHAKE_MAG_DSP_BL_READY 0xFEFE0000 /* At start DSP writes this when bootloader ready */
-#define HANDSHAKE_MAG_DSP_ENTRY 0x01000000 /* Dsp writes this to request for entry address */
-#define HANDSHAKE_MAG_DSP_DATA 0x02000000 /* Dsp writes this to request for data block */
-#define HANDSHAKE_MAG_DSP_DONE 0x03000000 /* Dsp writes this to indicate download done */
-
-#define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */
-#define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB /* Driver writes this to indicate data available to DSP */
-#define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB /* Driver writes this to indicate entry point to DSP */
-
-#define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
-
-
-/* New Magnemite downloader */
-#define DWNLD_MAG1_HANDSHAKE_LOC 0x00
-#define DWNLD_MAG1_TYPE_LOC 0x01
-#define DWNLD_MAG1_SIZE_LOC 0x02
-#define DWNLD_MAG1_PS_HDR_LOC 0x03
-
-struct dsp_file_hdr {
- long version_id; /* Version ID of this image format. */
- long package_id; /* Package ID of code release. */
- long build_date; /* Date/time stamp when file was built. */
- long commands_offset; /* Offset to attached commands in Pseudo Hdr format. */
- long loader_offset; /* Offset to bootloader code. */
- long loader_code_address; /* Start address of bootloader. */
- long loader_code_end; /* Where bootloader code ends. */
- long loader_code_size;
- long version_data_offset; /* Offset were scrambled version data begins. */
- long version_data_size; /* Size, in words, of scrambled version data. */
- long nDspImages; /* Number of DSP images in file. */
-};
-
-struct dsp_image_info {
- long coff_date; /* Date/time when DSP Coff image was built. */
- long begin_offset; /* Offset in file where image begins. */
- long end_offset; /* Offset in file where image begins. */
- long run_address; /* On chip Start address of DSP code. */
- long image_size; /* Size of image. */
- long version; /* Embedded version # of DSP code. */
- unsigned short checksum; /* DSP File checksum */
- unsigned short pad1;
-} __packed;
-
-
-/* checks if the doorbell register is cleared */
-static int check_usb_db(struct ft1000_usb *ft1000dev)
-{
- int loopcnt;
- u16 temp;
- int status;
-
- loopcnt = 0;
-
- while (loopcnt < 10) {
- status = ft1000_read_register(ft1000dev, &temp,
- FT1000_REG_DOORBELL);
- pr_debug("read FT1000_REG_DOORBELL value is %x\n", temp);
- if (temp & 0x0080) {
- pr_debug("Got checkusb doorbell\n");
- status = ft1000_write_register(ft1000dev, 0x0080,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(ft1000dev, 0x0100,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(ft1000dev, 0x8000,
- FT1000_REG_DOORBELL);
- break;
- }
- loopcnt++;
- usleep_range(10000, 11000);
-
- }
-
- loopcnt = 0;
- while (loopcnt < 20) {
- status = ft1000_read_register(ft1000dev, &temp,
- FT1000_REG_DOORBELL);
- pr_debug("Doorbell = 0x%x\n", temp);
- if (temp & 0x8000) {
- loopcnt++;
- usleep_range(10000, 11000);
- } else {
- pr_debug("door bell is cleared, return 0\n");
- return 0;
- }
- }
-
- return -1;
-}
-
-/* gets the handshake and compares it with the expected value */
-static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value)
-{
- u16 handshake;
- int loopcnt;
- int status = 0;
-
- loopcnt = 0;
-
- while (loopcnt < 100) {
- /* Need to clear downloader doorbell if Hartley ASIC */
- status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_RX,
- FT1000_REG_DOORBELL);
- if (ft1000dev->fcodeldr) {
- pr_debug("fcodeldr is %d\n", ft1000dev->fcodeldr);
- ft1000dev->fcodeldr = 0;
- status = check_usb_db(ft1000dev);
- if (status != 0) {
- pr_debug("check_usb_db failed\n");
- break;
- }
- status = ft1000_write_register(ft1000dev,
- FT1000_DB_DNLD_RX,
- FT1000_REG_DOORBELL);
- }
-
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- handshake = ntohs(handshake);
-
- if (status)
- return HANDSHAKE_TIMEOUT_VALUE;
-
- if ((handshake == expected_value) ||
- (handshake == HANDSHAKE_RESET_VALUE_USB)) {
- return handshake;
- }
- loopcnt++;
- usleep_range(10000, 11000);
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-}
-
-/* write the handshake value to the handshake location */
-static void put_handshake(struct ft1000_usb *ft1000dev, u16 handshake_value)
-{
- u32 tempx;
- u16 tempword;
- int status;
-
- tempx = (u32)handshake_value;
- tempx = ntohl(tempx);
-
- tempword = (u16)(tempx & 0xffff);
- status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
- tempword, 0);
- tempword = (u16)(tempx >> 16);
- status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
- tempword, 1);
- status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
- FT1000_REG_DOORBELL);
-}
-
-static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value)
-{
- u16 handshake;
- int loopcnt;
- u16 temp;
- int status = 0;
-
- loopcnt = 0;
- handshake = 0;
-
- while (loopcnt < 100) {
- if (ft1000dev->usbboot == 2) {
- status = ft1000_read_dpram32(ft1000dev, 0,
- (u8 *)&ft1000dev->tempbuf[0], 64);
- for (temp = 0; temp < 16; temp++) {
- pr_debug("tempbuf %d = 0x%x\n",
- temp, ft1000dev->tempbuf[temp]);
- }
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- pr_debug("handshake from read_dpram16 = 0x%x\n",
- handshake);
- if (ft1000dev->dspalive == ft1000dev->tempbuf[6]) {
- handshake = 0;
- } else {
- handshake = ft1000dev->tempbuf[1];
- ft1000dev->dspalive =
- ft1000dev->tempbuf[6];
- }
- } else {
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC,
- (u8 *)&handshake, 1);
- }
-
- loopcnt++;
- usleep_range(10000, 11000);
- handshake = ntohs(handshake);
- if ((handshake == expected_value) ||
- (handshake == HANDSHAKE_RESET_VALUE_USB))
- return handshake;
- }
-
- return HANDSHAKE_TIMEOUT_VALUE;
-}
-
-static void put_handshake_usb(struct ft1000_usb *ft1000dev, u16 handshake_value)
-{
- int i;
-
- for (i = 0; i < 1000; i++)
- ;
-}
-
-static u16 get_request_type(struct ft1000_usb *ft1000dev)
-{
- u16 request_type;
- int status;
- u16 tempword;
- u32 tempx;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempx);
- tempx = ntohl(tempx);
- } else {
- tempx = 0;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempword, 1);
- tempx |= (tempword << 16);
- tempx = ntohl(tempx);
- }
- request_type = (u16)tempx;
-
- return request_type;
-}
-
-static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
-{
- u16 request_type;
- int status;
- u16 tempword;
- u32 tempx;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempx);
- tempx = ntohl(tempx);
- } else {
- if (ft1000dev->usbboot == 2) {
- tempx = ft1000dev->tempbuf[2];
- tempword = ft1000dev->tempbuf[3];
- } else {
- tempx = 0;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_TYPE_LOC,
- (u8 *)&tempword, 1);
- }
- tempx |= (tempword << 16);
- tempx = ntohl(tempx);
- }
- request_type = (u16)tempx;
-
- return request_type;
-}
-
-static long get_request_value(struct ft1000_usb *ft1000dev)
-{
- u32 value;
- u16 tempword;
- int status;
-
- if (ft1000dev->bootmode == 1) {
- status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&value);
- value = ntohl(value);
- } else {
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempword, 0);
- value = tempword;
- status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempword, 1);
- value |= (tempword << 16);
- value = ntohl(value);
- }
-
- return value;
-}
-
-
-/* writes a value to DWNLD_MAG1_SIZE_LOC */
-static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue)
-{
- u32 tempx;
- int status;
-
- tempx = ntohl(lvalue);
- status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
- (u8 *)&tempx);
-}
-
-
-
-/* returns the checksum of the pseudo header */
-static u16 hdr_checksum(struct pseudo_hdr *pHdr)
-{
- u16 *usPtr = (u16 *)pHdr;
- u16 chksum;
-
-
- chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
- usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
-
- return chksum;
-}
-
-static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (buff_w[i] != buff_r[i + offset])
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static int write_dpram32_and_check(struct ft1000_usb *ft1000dev,
- u16 tempbuffer[], u16 dpram)
-{
- int status;
- u16 resultbuffer[64];
- int i;
-
- for (i = 0; i < 10; i++) {
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 64);
- if (status == 0) {
- /* Work around for ASIC bit stuffing problem. */
- if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
- status = ft1000_write_dpram32(ft1000dev,
- dpram+12, (u8 *)&tempbuffer[24],
- 64);
- }
- /* Let's check the data written */
- status = ft1000_read_dpram32(ft1000dev, dpram,
- (u8 *)&resultbuffer[0], 64);
- if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
- if (check_buffers(tempbuffer, resultbuffer, 28,
- 0)) {
- pr_debug("DPRAM write failed 1 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- status = ft1000_read_dpram32(ft1000dev,
- dpram+12,
- (u8 *)&resultbuffer[0], 64);
-
- if (check_buffers(tempbuffer, resultbuffer, 16,
- 24)) {
- pr_debug("DPRAM write failed 2 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- } else {
- if (check_buffers(tempbuffer, resultbuffer, 32,
- 0)) {
- pr_debug("DPRAM write failed 3 during bootloading\n");
- usleep_range(9000, 11000);
- break;
- }
- }
- if (status == 0)
- break;
- }
- }
- return status;
-}
-
-/* writes a block of DSP image to DPRAM
- * Parameters: struct ft1000_usb - device structure
- * u16 **pUsFile - DSP image file pointer in u16
- * u8 **pUcFile - DSP image file pointer in u8
- * long word_length - length of the buffer to be written to DPRAM
- */
-static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile,
- long word_length)
-{
- int status = 0;
- u16 dpram;
- int loopcnt, i;
- u16 tempword;
- u16 tempbuffer[64];
-
- /*pr_debug("start word_length = %d\n",(int)word_length); */
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- tempword = *(*pUsFile);
- (*pUsFile)++;
- status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
- tempword = *(*pUsFile);
- (*pUsFile)++;
- status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
-
- *pUcFile = *pUcFile + 4;
- word_length--;
- tempword = (u16)word_length;
- word_length = (word_length / 16) + 1;
- for (; word_length > 0; word_length--) { /* In words */
- loopcnt = 0;
- for (i = 0; i < 32; i++) {
- if (tempword != 0) {
- tempbuffer[i++] = *(*pUsFile);
- (*pUsFile)++;
- tempbuffer[i] = *(*pUsFile);
- (*pUsFile)++;
- *pUcFile = *pUcFile + 4;
- loopcnt++;
- tempword--;
- } else {
- tempbuffer[i++] = 0;
- tempbuffer[i] = 0;
- }
- }
-
- /*pr_debug("loopcnt is %d\n", loopcnt); */
- /*pr_debug("write_blk: bootmode = %d\n", bootmode); */
- /*pr_debug("write_blk: dpram = %x\n", dpram); */
- if (ft1000dev->bootmode == 0) {
- if (dpram >= 0x3F4)
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 8);
- else
- status = ft1000_write_dpram32(ft1000dev, dpram,
- (u8 *)&tempbuffer[0], 64);
- } else {
- status = write_dpram32_and_check(ft1000dev, tempbuffer,
- dpram);
- if (status != 0) {
- pr_debug("Write failed tempbuffer[31] = 0x%x\n",
- tempbuffer[31]);
- break;
- }
- }
- dpram = dpram + loopcnt;
- }
- return status;
-}
-
-static void usb_dnld_complete(struct urb *urb)
-{
- /* pr_debug("****** usb_dnld_complete\n"); */
-}
-
-/* writes a block of DSP image to DPRAM
- * Parameters: struct ft1000_usb - device structure
- * u16 **pUsFile - DSP image file pointer in u16
- * u8 **pUcFile - DSP image file pointer in u8
- * long word_length - length of the buffer to be written to DPRAM
- */
-static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
- u8 **pUcFile, long word_length)
-{
- int byte_length;
-
- byte_length = word_length * 4;
-
- if (byte_length && ((byte_length % 64) == 0))
- byte_length += 4;
-
- if (byte_length < 64)
- byte_length = 68;
-
- usb_init_urb(ft1000dev->tx_urb);
- memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
- usb_fill_bulk_urb(ft1000dev->tx_urb,
- ft1000dev->dev,
- usb_sndbulkpipe(ft1000dev->dev,
- ft1000dev->bulk_out_endpointAddr),
- ft1000dev->tx_buf, byte_length, usb_dnld_complete,
- ft1000dev);
-
- usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
-
- *pUsFile = *pUsFile + (word_length << 1);
- *pUcFile = *pUcFile + (word_length << 2);
-
- return 0;
-}
-
-static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake,
- u32 *state)
-{
- int status = 0;
-
- if (ft1000dev->usbboot)
- *hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
- else
- *hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
- if (*hshake == HANDSHAKE_DSP_BL_READY) {
- pr_debug("handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
- put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
- } else if (*hshake == HANDSHAKE_TIMEOUT_VALUE) {
- status = -ETIMEDOUT;
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -ENETRESET;
- }
- *state = STATE_BOOT_DWNLD;
- return status;
-}
-
-static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
- u8 **c_file, const u8 *endpoint, bool boot_case)
-{
- long word_length;
- int status = 0;
-
- word_length = get_request_value(ft1000dev);
- /*pr_debug("word_length = 0x%x\n", (int)word_length); */
- /*NdisMSleep (100); */
- if (word_length > MAX_LENGTH) {
- pr_debug("Download error: Max length exceeded\n");
- return -1;
- }
- if ((word_length * 2 + (long)c_file) > (long)endpoint) {
- /* Error, beyond boot code range.*/
- pr_debug("Download error: Requested len=%d exceeds BOOT code boundary\n",
- (int)word_length);
- return -1;
- }
- if (word_length & 0x1)
- word_length++;
- word_length = word_length / 2;
-
- if (boot_case) {
- status = write_blk(ft1000dev, s_file, c_file, word_length);
- /*pr_debug("write_blk returned %d\n", status); */
- } else {
- status = write_blk_fifo(ft1000dev, s_file, c_file, word_length);
- if (ft1000dev->usbboot == 0)
- ft1000dev->usbboot++;
- if (ft1000dev->usbboot == 1)
- status |= ft1000_write_dpram16(ft1000dev,
- DWNLD_MAG1_PS_HDR_LOC, 0, 0);
- }
- return status;
-}
-
-/* Scramble downloader for Harley based ASIC via USB interface */
-int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
- u32 FileLength)
-{
- int status = 0;
- u32 state;
- u16 handshake;
- struct pseudo_hdr *pseudo_header;
- u16 pseudo_header_len;
- long word_length;
- u16 request;
- u16 temp;
-
- struct dsp_file_hdr *file_hdr;
- struct dsp_image_info *dsp_img_info = NULL;
- long requested_version;
- bool correct_version;
- struct drv_msg *mailbox_data;
- u16 *data = NULL;
- u16 *s_file = NULL;
- u8 *c_file = NULL;
- u8 *boot_end = NULL, *code_end = NULL;
- int image;
- long loader_code_address, loader_code_size = 0;
- long run_address = 0, run_size = 0;
-
- u32 templong;
- u32 image_chksum = 0;
-
- u16 dpram = 0;
- u8 *pbuffer;
- struct prov_record *pprov_record;
- struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
-
- ft1000dev->fcodeldr = 0;
- ft1000dev->usbboot = 0;
- ft1000dev->dspalive = 0xffff;
-
- /*
- * Get version id of file, at first 4 bytes of file, for newer files.
- */
-
- state = STATE_START_DWNLD;
-
- file_hdr = pFileStart;
-
- ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
-
- s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
- c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
-
- boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
-
- loader_code_address = file_hdr->loader_code_address;
- loader_code_size = file_hdr->loader_code_size;
- correct_version = false;
-
- while ((status == 0) && (state != STATE_DONE_FILE)) {
- switch (state) {
- case STATE_START_DWNLD:
- status = scram_start_dwnld(ft1000dev, &handshake,
- &state);
- break;
-
- case STATE_BOOT_DWNLD:
- pr_debug("STATE_BOOT_DWNLD\n");
- ft1000dev->bootmode = 1;
- handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- request = get_request_type(ft1000dev);
- switch (request) {
- case REQUEST_RUN_ADDRESS:
- pr_debug("REQUEST_RUN_ADDRESS\n");
- put_request_value(ft1000dev,
- loader_code_address);
- break;
- case REQUEST_CODE_LENGTH:
- pr_debug("REQUEST_CODE_LENGTH\n");
- put_request_value(ft1000dev,
- loader_code_size);
- break;
- case REQUEST_DONE_BL:
- pr_debug("REQUEST_DONE_BL\n");
- /* Reposition ptrs to beginning of code section */
- s_file = (u16 *) (boot_end);
- c_file = (u8 *) (boot_end);
- /* pr_debug("download:s_file = 0x%8x\n", (int)s_file); */
- /* pr_debug("FT1000:download:c_file = 0x%8x\n", (int)c_file); */
- state = STATE_CODE_DWNLD;
- ft1000dev->fcodeldr = 1;
- break;
- case REQUEST_CODE_SEGMENT:
- status = request_code_segment(ft1000dev,
- &s_file, &c_file,
- boot_end,
- true);
- break;
- default:
- pr_debug("Download error: Bad request type=%d in BOOT download state\n",
- request);
- status = -1;
- break;
- }
- if (ft1000dev->usbboot)
- put_handshake_usb(ft1000dev,
- HANDSHAKE_RESPONSE);
- else
- put_handshake(ft1000dev,
- HANDSHAKE_RESPONSE);
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -1;
- }
-
- break;
-
- case STATE_CODE_DWNLD:
- /* pr_debug("STATE_CODE_DWNLD\n"); */
- ft1000dev->bootmode = 0;
- if (ft1000dev->usbboot)
- handshake =
- get_handshake_usb(ft1000dev,
- HANDSHAKE_REQUEST);
- else
- handshake =
- get_handshake(ft1000dev, HANDSHAKE_REQUEST);
- if (handshake == HANDSHAKE_REQUEST) {
- /*
- * Get type associated with the request.
- */
- if (ft1000dev->usbboot)
- request =
- get_request_type_usb(ft1000dev);
- else
- request = get_request_type(ft1000dev);
- switch (request) {
- case REQUEST_FILE_CHECKSUM:
- pr_debug("image_chksum = 0x%8x\n",
- image_chksum);
- put_request_value(ft1000dev,
- image_chksum);
- break;
- case REQUEST_RUN_ADDRESS:
- pr_debug("REQUEST_RUN_ADDRESS\n");
- if (correct_version) {
- pr_debug("run_address = 0x%8x\n",
- (int)run_address);
- put_request_value(ft1000dev,
- run_address);
- } else {
- pr_debug("Download error: Got Run address request before image offset request\n");
- status = -1;
- break;
- }
- break;
- case REQUEST_CODE_LENGTH:
- pr_debug("REQUEST_CODE_LENGTH\n");
- if (correct_version) {
- pr_debug("run_size = 0x%8x\n",
- (int)run_size);
- put_request_value(ft1000dev,
- run_size);
- } else {
- pr_debug("Download error: Got Size request before image offset request\n");
- status = -1;
- break;
- }
- break;
- case REQUEST_DONE_CL:
- ft1000dev->usbboot = 3;
- /* Reposition ptrs to beginning of provisioning section */
- s_file =
- (u16 *) (pFileStart +
- file_hdr->commands_offset);
- c_file =
- (u8 *) (pFileStart +
- file_hdr->commands_offset);
- state = STATE_DONE_DWNLD;
- break;
- case REQUEST_CODE_SEGMENT:
- /* pr_debug("REQUEST_CODE_SEGMENT - CODELOADER\n"); */
- if (!correct_version) {
- pr_debug("Download error: Got Code Segment request before image offset request\n");
- status = -1;
- break;
- }
-
- status = request_code_segment(ft1000dev,
- &s_file, &c_file,
- code_end,
- false);
-
- break;
-
- case REQUEST_MAILBOX_DATA:
- pr_debug("REQUEST_MAILBOX_DATA\n");
- /* Convert length from byte count to word count. Make sure we round up. */
- word_length =
- (long)(pft1000info->DSPInfoBlklen +
- 1) / 2;
- put_request_value(ft1000dev,
- word_length);
- mailbox_data =
- (struct drv_msg *)&(pft1000info->
- DSPInfoBlk[0]);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
-
- data = (u16 *)&mailbox_data->data[0];
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- if (word_length & 0x1)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
-
- templong = *data++;
- templong |= (*data++ << 16);
- status =
- fix_ft1000_write_dpram32
- (ft1000dev, dpram++,
- (u8 *)&templong);
-
- }
- break;
-
- case REQUEST_VERSION_INFO:
- pr_debug("REQUEST_VERSION_INFO\n");
- word_length =
- file_hdr->version_data_size;
- put_request_value(ft1000dev,
- word_length);
- /*
- * Position ASIC DPRAM auto-increment pointer.
- */
-
- s_file =
- (u16 *) (pFileStart +
- file_hdr->
- version_data_offset);
-
- dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
- if (word_length & 0x1)
- word_length++;
-
- word_length = word_length / 2;
-
- for (; word_length > 0; word_length--) { /* In words */
-
- templong = ntohs(*s_file++);
- temp = ntohs(*s_file++);
- templong |= (temp << 16);
- status =
- fix_ft1000_write_dpram32
- (ft1000dev, dpram++,
- (u8 *)&templong);
-
- }
- break;
-
- case REQUEST_CODE_BY_VERSION:
- pr_debug("REQUEST_CODE_BY_VERSION\n");
- correct_version = false;
- requested_version =
- get_request_value(ft1000dev);
-
- dsp_img_info =
- (struct dsp_image_info *)(pFileStart
- +
- sizeof
- (struct
- dsp_file_hdr));
-
- for (image = 0;
- image < file_hdr->nDspImages;
- image++) {
-
- if (dsp_img_info->version ==
- requested_version) {
- correct_version = true;
- pr_debug("correct_version is TRUE\n");
- s_file =
- (u16 *) (pFileStart
- +
- dsp_img_info->
- begin_offset);
- c_file =
- (u8 *) (pFileStart +
- dsp_img_info->
- begin_offset);
- code_end =
- (u8 *) (pFileStart +
- dsp_img_info->
- end_offset);
- run_address =
- dsp_img_info->
- run_address;
- run_size =
- dsp_img_info->
- image_size;
- image_chksum =
- (u32)dsp_img_info->
- checksum;
- break;
- }
- dsp_img_info++;
-
- } /* end of for */
-
- if (!correct_version) {
- /*
- * Error, beyond boot code range.
- */
- pr_debug("Download error: Bad Version Request = 0x%x.\n",
- (int)requested_version);
- status = -1;
- break;
- }
- break;
-
- default:
- pr_debug("Download error: Bad request type=%d in CODE download state.\n",
- request);
- status = -1;
- break;
- }
- if (ft1000dev->usbboot)
- put_handshake_usb(ft1000dev,
- HANDSHAKE_RESPONSE);
- else
- put_handshake(ft1000dev,
- HANDSHAKE_RESPONSE);
- } else {
- pr_debug("Download error: Handshake failed\n");
- status = -1;
- }
-
- break;
-
- case STATE_DONE_DWNLD:
- pr_debug("Code loader is done...\n");
- state = STATE_SECTION_PROV;
- break;
-
- case STATE_SECTION_PROV:
- pr_debug("STATE_SECTION_PROV\n");
- pseudo_header = (struct pseudo_hdr *)c_file;
-
- if (pseudo_header->checksum ==
- hdr_checksum(pseudo_header)) {
- if (pseudo_header->portdest !=
- 0x80 /* Dsp OAM */) {
- state = STATE_DONE_PROV;
- break;
- }
- pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */
-
- /* Get buffer for provisioning data */
- pbuffer =
- kmalloc(pseudo_header_len +
- sizeof(struct pseudo_hdr),
- GFP_ATOMIC);
- if (pbuffer) {
- memcpy(pbuffer, c_file,
- (u32) (pseudo_header_len +
- sizeof(struct
- pseudo_hdr)));
- /* link provisioning data */
- pprov_record =
- kmalloc(sizeof(struct prov_record),
- GFP_ATOMIC);
- if (pprov_record) {
- pprov_record->pprov_data =
- pbuffer;
- list_add_tail(&pprov_record->
- list,
- &pft1000info->
- prov_list);
- /* Move to next entry if available */
- c_file =
- (u8 *) ((unsigned long)
- c_file +
- (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
- if ((unsigned long)(c_file) -
- (unsigned long)(pFileStart)
- >=
- (unsigned long)FileLength) {
- state = STATE_DONE_FILE;
- }
- } else {
- kfree(pbuffer);
- status = -1;
- }
- } else {
- status = -1;
- }
- } else {
- /* Checksum did not compute */
- status = -1;
- }
- pr_debug("after STATE_SECTION_PROV, state = %d, status= %d\n",
- state, status);
- break;
-
- case STATE_DONE_PROV:
- pr_debug("STATE_DONE_PROV\n");
- state = STATE_DONE_FILE;
- break;
-
- default:
- status = -1;
- break;
- } /* End Switch */
-
- if (status != 0)
- break;
-
-/****
- // Check if Card is present
- status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
- if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
- break;
- }
-
- status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
- if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
- break;
- }
-****/
-
- } /* End while */
-
- pr_debug("Download exiting with status = 0x%8x\n", status);
- ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
- FT1000_REG_DOORBELL);
-
- return status;
-}
+++ /dev/null
-/* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- *
- * This file is part of Express Card USB Driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include "ft1000_usb.h"
-#include <linux/types.h>
-
-#define HARLEY_READ_REGISTER 0x0
-#define HARLEY_WRITE_REGISTER 0x01
-#define HARLEY_READ_DPRAM_32 0x02
-#define HARLEY_READ_DPRAM_LOW 0x03
-#define HARLEY_READ_DPRAM_HIGH 0x04
-#define HARLEY_WRITE_DPRAM_32 0x05
-#define HARLEY_WRITE_DPRAM_LOW 0x06
-#define HARLEY_WRITE_DPRAM_HIGH 0x07
-
-#define HARLEY_READ_OPERATION 0xc1
-#define HARLEY_WRITE_OPERATION 0x41
-
-#if 0
-#define JDEBUG
-#endif
-
-static int ft1000_submit_rx_urb(struct ft1000_info *info);
-
-static u8 tempbuffer[1600];
-
-#define MAX_RCV_LOOP 100
-
-/* send a control message via USB interface synchronously
- * Parameters: ft1000_usb - device structure
- * pipe - usb control message pipe
- * request - control request
- * requesttype - control message request type
- * value - value to be written or 0
- * index - register index
- * data - data buffer to hold the read/write values
- * size - data size
- * timeout - control message time out value
- */
-static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size, int timeout)
-{
- int ret;
-
- if ((ft1000dev == NULL) || (ft1000dev->dev == NULL)) {
- pr_debug("ft1000dev or ft1000dev->dev == NULL, failure\n");
- return -ENODEV;
- }
-
- ret = usb_control_msg(ft1000dev->dev, pipe, request, requesttype,
- value, index, data, size, timeout);
-
- if (ret > 0)
- ret = 0;
-
- return ret;
-}
-
-/* returns the value in a register */
-int ft1000_read_register(struct ft1000_usb *ft1000dev, u16 *Data,
- u16 nRegIndx)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- HARLEY_READ_REGISTER,
- HARLEY_READ_OPERATION,
- 0,
- nRegIndx,
- Data,
- 2,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* writes the value in a register */
-int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value,
- u16 nRegIndx)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- HARLEY_WRITE_REGISTER,
- HARLEY_WRITE_OPERATION,
- value,
- nRegIndx,
- NULL,
- 0,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read a number of bytes from DPRAM */
-int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u16 cnt)
-{
- int ret = 0;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- HARLEY_READ_DPRAM_32,
- HARLEY_READ_OPERATION,
- 0,
- indx,
- buffer,
- cnt,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* writes into DPRAM a number of bytes */
-int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u16 cnt)
-{
- int ret = 0;
-
- if (cnt % 4)
- cnt += cnt - (cnt % 4);
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- HARLEY_WRITE_DPRAM_32,
- HARLEY_WRITE_OPERATION,
- 0,
- indx,
- buffer,
- cnt,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read 16 bits from DPRAM */
-int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer,
- u8 highlow)
-{
- int ret = 0;
- u8 request;
-
- if (highlow == 0)
- request = HARLEY_READ_DPRAM_LOW;
- else
- request = HARLEY_READ_DPRAM_HIGH;
-
- ret = ft1000_control(ft1000dev,
- usb_rcvctrlpipe(ft1000dev->dev, 0),
- request,
- HARLEY_READ_OPERATION,
- 0,
- indx,
- buffer,
- 2,
- USB_CTRL_GET_TIMEOUT);
-
- return ret;
-}
-
-/* write into DPRAM a number of bytes */
-int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value,
- u8 highlow)
-{
- int ret = 0;
- u8 request;
-
- if (highlow == 0)
- request = HARLEY_WRITE_DPRAM_LOW;
- else
- request = HARLEY_WRITE_DPRAM_HIGH;
-
- ret = ft1000_control(ft1000dev,
- usb_sndctrlpipe(ft1000dev->dev, 0),
- request,
- HARLEY_WRITE_OPERATION,
- value,
- indx,
- NULL,
- 0,
- USB_CTRL_SET_TIMEOUT);
-
- return ret;
-}
-
-/* read DPRAM 4 words at a time */
-int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx,
- u8 *buffer)
-{
- u8 buf[16];
- u16 pos;
- int ret = 0;
-
- pos = (indx / 4) * 4;
- ret = ft1000_read_dpram32(ft1000dev, pos, buf, 16);
-
- if (ret == 0) {
- pos = (indx % 4) * 4;
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- *buffer++ = buf[pos++];
- } else {
- pr_debug("DPRAM32 Read failed\n");
- *buffer++ = 0;
- *buffer++ = 0;
- *buffer++ = 0;
- *buffer++ = 0;
- }
-
- return ret;
-}
-
-
-/* Description: This function write to DPRAM 4 words at a time */
-int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer)
-{
- u16 pos1;
- u16 pos2;
- u16 i;
- u8 buf[32];
- u8 resultbuffer[32];
- u8 *pdata;
- int ret = 0;
-
- pos1 = (indx / 4) * 4;
- pdata = buffer;
- ret = ft1000_read_dpram32(ft1000dev, pos1, buf, 16);
-
- if (ret == 0) {
- pos2 = (indx % 4)*4;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- buf[pos2++] = *buffer++;
- ret = ft1000_write_dpram32(ft1000dev, pos1, buf, 16);
- } else {
- pr_debug("DPRAM32 Read failed\n");
- return ret;
- }
-
- ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16);
-
- if (ret == 0) {
- buffer = pdata;
- for (i = 0; i < 16; i++) {
- if (buf[i] != resultbuffer[i])
- ret = -1;
- }
- }
-
- if (ret == -1) {
- ret = ft1000_write_dpram32(ft1000dev, pos1,
- (u8 *)&tempbuffer[0], 16);
- ret = ft1000_read_dpram32(ft1000dev, pos1,
- (u8 *)&resultbuffer[0], 16);
- if (ret == 0) {
- buffer = pdata;
- for (i = 0; i < 16; i++) {
- if (tempbuffer[i] != resultbuffer[i]) {
- ret = -1;
- pr_debug("Failed to write\n");
- }
- }
- }
- }
-
- return ret;
-}
-
-/* reset or activate the DSP */
-static void card_reset_dsp(struct ft1000_usb *ft1000dev, bool value)
-{
- int status = 0;
- u16 tempword;
-
- status = ft1000_write_register(ft1000dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_SUP_CTRL);
-
- if (value) {
- pr_debug("Reset DSP\n");
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword |= DSP_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- } else {
- pr_debug("Activate DSP\n");
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword |= DSP_ENCRYPTED;
- tempword &= ~DSP_UNENCRYPTED;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- tempword &= ~EFUSE_MEM_DISABLE;
- tempword &= ~DSP_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword,
- FT1000_REG_RESET);
- status = ft1000_read_register(ft1000dev, &tempword,
- FT1000_REG_RESET);
- }
-}
-
-/* send a command to ASIC
- * Parameters: ft1000_usb - device structure
- * ptempbuffer - command buffer
- * size - command buffer size
- */
-int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer,
- int size)
-{
- int ret;
- unsigned short temp;
- unsigned char *commandbuf;
-
- pr_debug("enter card_send_command... size=%d\n", size);
-
- ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
- if (ret)
- return ret;
-
- commandbuf = kmalloc(size + 2, GFP_KERNEL);
- if (!commandbuf)
- return -ENOMEM;
- memcpy((void *)commandbuf + 2, ptempbuffer, size);
-
- if (temp & 0x0100)
- usleep_range(900, 1100);
-
- /* check for odd word */
- size = size + 2;
-
- /* Must force to be 32 bit aligned */
- if (size % 4)
- size += 4 - (size % 4);
-
- ret = ft1000_write_dpram32(ft1000dev, 0, commandbuf, size);
- if (ret)
- return ret;
- usleep_range(900, 1100);
- ret = ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
- if (ret)
- return ret;
- usleep_range(900, 1100);
-
- ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
-
-#if 0
- if ((temp & 0x0100) == 0)
- pr_debug("Message sent\n");
-#endif
- return ret;
-}
-
-/* load or reload the DSP */
-int dsp_reload(struct ft1000_usb *ft1000dev)
-{
- int status;
- u16 tempword;
- u32 templong;
-
- struct ft1000_info *pft1000info;
-
- pft1000info = netdev_priv(ft1000dev->net);
-
- pft1000info->CardReady = 0;
-
- /* Program Interrupt Mask register */
- status = ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_SUP_IMASK);
-
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
- tempword |= ASIC_RESET_BIT;
- status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
- msleep(1000);
- status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
- pr_debug("Reset Register = 0x%x\n", tempword);
-
- /* Toggle DSP reset */
- card_reset_dsp(ft1000dev, 1);
- msleep(1000);
- card_reset_dsp(ft1000dev, 0);
- msleep(1000);
-
- status = ft1000_write_register(ft1000dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
-
- /* Let's check for FEFE */
- status =
- ft1000_read_dpram32(ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX,
- (u8 *)&templong, 4);
- pr_debug("templong (fefe) = 0x%8x\n", templong);
-
- /* call codeloader */
- status = scram_dnldr(ft1000dev, pFileStart, FileLength);
-
- if (status != 0)
- return -EIO;
-
- msleep(1000);
-
- return 0;
-}
-
-/* call the Card Service function to reset the ASIC. */
-static void ft1000_reset_asic(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_usb *ft1000dev = info->priv;
- u16 tempword;
-
- /* Let's use the register provided by the Magnemite ASIC to reset the
- * ASIC and DSP.
- */
- ft1000_write_register(ft1000dev, DSP_RESET_BIT | ASIC_RESET_BIT,
- FT1000_REG_RESET);
-
- mdelay(1);
-
- /* set watermark to -1 in order to not generate an interrupt */
- ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_MAG_WATERMARK);
-
- /* clear interrupts */
- ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
- ft1000_write_register(ft1000dev, tempword, FT1000_REG_SUP_ISR);
- ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
- pr_debug("interrupt status register = 0x%x\n", tempword);
-}
-
-static int ft1000_reset_card(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
- struct ft1000_usb *ft1000dev = info->priv;
- u16 tempword;
- struct prov_record *ptr;
- struct prov_record *tmp;
-
- ft1000dev->fCondResetPend = true;
- info->CardReady = 0;
- ft1000dev->fProvComplete = false;
-
- /* Make sure we free any memory reserve for provisioning */
- list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
- pr_debug("deleting provisioning record\n");
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
-
- pr_debug("reset asic\n");
- ft1000_reset_asic(dev);
-
- pr_debug("call dsp_reload\n");
- dsp_reload(ft1000dev);
-
- pr_debug("dsp reload successful\n");
-
- mdelay(10);
-
- /* Initialize DSP heartbeat area */
- ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag,
- FT1000_MAG_HI_HO_INDX);
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (u8 *)&tempword,
- FT1000_MAG_HI_HO_INDX);
- pr_debug("hi_ho value = 0x%x\n", tempword);
-
- info->CardReady = 1;
-
- ft1000dev->fCondResetPend = false;
-
- return TRUE;
-}
-
-/* callback function when a urb is transmitted */
-static void ft1000_usb_transmit_complete(struct urb *urb)
-{
-
- struct ft1000_usb *ft1000dev = urb->context;
-
- if (urb->status)
- pr_err("%s: TX status %d\n", ft1000dev->net->name, urb->status);
-
- netif_wake_queue(ft1000dev->net);
-}
-
-/* take an ethernet packet and convert it to a Flarion
- * packet prior to sending it to the ASIC Downlink FIFO.
- */
-static int ft1000_copy_down_pkt(struct net_device *netdev, u8 *packet, u16 len)
-{
- struct ft1000_info *pInfo = netdev_priv(netdev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
-
- int count, ret;
- u8 *t;
- struct pseudo_hdr hdr;
-
- if (!pInfo->CardReady) {
- pr_debug("Card Not Ready\n");
- return -ENODEV;
- }
-
- count = sizeof(struct pseudo_hdr) + len;
- if (count > MAX_BUF_SIZE) {
- pr_debug("Message Size Overflow! size = %d\n", count);
- return -EINVAL;
- }
-
- if (count % 4)
- count = count + (4 - (count % 4));
-
- memset(&hdr, 0, sizeof(struct pseudo_hdr));
-
- hdr.length = ntohs(count);
- hdr.source = 0x10;
- hdr.destination = 0x20;
- hdr.portdest = 0x20;
- hdr.portsrc = 0x10;
- hdr.sh_str_id = 0x91;
- hdr.control = 0x00;
-
- hdr.checksum = hdr.length ^ hdr.source ^ hdr.destination ^
- hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^ hdr.control;
-
- memcpy(&pFt1000Dev->tx_buf[0], &hdr, sizeof(hdr));
- memcpy(&pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)], packet, len);
-
- netif_stop_queue(netdev);
-
- usb_fill_bulk_urb(pFt1000Dev->tx_urb,
- pFt1000Dev->dev,
- usb_sndbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_out_endpointAddr),
- pFt1000Dev->tx_buf, count,
- ft1000_usb_transmit_complete, pFt1000Dev);
-
- t = (u8 *)pFt1000Dev->tx_urb->transfer_buffer;
-
- ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC);
-
- if (ret) {
- pr_debug("failed tx_urb %d\n", ret);
- return ret;
- }
- pInfo->stats.tx_packets++;
- pInfo->stats.tx_bytes += (len + 14);
-
- return 0;
-}
-
-/* transmit an ethernet packet
- * Parameters: skb - socket buffer to be sent
- * dev - network device
- */
-static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ft1000_info *pInfo = netdev_priv(dev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
- u8 *pdata;
- int maxlen, pipe;
-
- if (skb == NULL) {
- pr_debug("skb == NULL!!!\n");
- return NETDEV_TX_OK;
- }
-
- if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- goto err;
- }
-
- pipe = usb_sndbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_out_endpointAddr);
- maxlen = usb_maxpacket(pFt1000Dev->dev, pipe, usb_pipeout(pipe));
-
- pdata = (u8 *)skb->data;
-
- if (pInfo->mediastate == 0) {
- /* Drop packet is mediastate is down */
- pr_debug("mediastate is down\n");
- goto err;
- }
-
- if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
- /* Drop packet which has invalid size */
- pr_debug("invalid ethernet length\n");
- goto err;
- }
-
- ft1000_copy_down_pkt(dev, pdata + ENET_HEADER_SIZE - 2,
- skb->len - ENET_HEADER_SIZE + 2);
-
-err:
- dev_kfree_skb(skb);
-
- return NETDEV_TX_OK;
-}
-
-/* open the network driver */
-static int ft1000_open(struct net_device *dev)
-{
- struct ft1000_info *pInfo = netdev_priv(dev);
- struct ft1000_usb *pFt1000Dev = pInfo->priv;
- struct timeval tv;
-
- pr_debug("ft1000_open is called for card %d\n", pFt1000Dev->CardNumber);
-
- pInfo->stats.rx_bytes = 0;
- pInfo->stats.tx_bytes = 0;
- pInfo->stats.rx_packets = 0;
- pInfo->stats.tx_packets = 0;
- do_gettimeofday(&tv);
- pInfo->ConTm = tv.tv_sec;
- pInfo->ProgConStat = 0;
-
- netif_start_queue(dev);
-
- netif_carrier_on(dev);
-
- return ft1000_submit_rx_urb(pInfo);
-}
-
-static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev)
-{
- struct ft1000_info *info = netdev_priv(dev);
-
- return &(info->stats);
-}
-
-static const struct net_device_ops ftnet_ops = {
- .ndo_open = &ft1000_open,
- .ndo_stop = &ft1000_close,
- .ndo_start_xmit = &ft1000_start_xmit,
- .ndo_get_stats = &ft1000_netdev_stats,
-};
-
-/* initialize the network device */
-static int ft1000_reset(void *dev)
-{
- ft1000_reset_card(dev);
- return 0;
-}
-
-int init_ft1000_netdev(struct ft1000_usb *ft1000dev)
-{
- struct net_device *netdev;
- struct ft1000_info *pInfo = NULL;
- struct dpram_blk *pdpram_blk;
- int i, ret_val;
- struct list_head *cur, *tmp;
- char card_nr[2];
- u8 gCardIndex = 0;
-
- netdev = alloc_etherdev(sizeof(struct ft1000_info));
- if (!netdev) {
- pr_debug("can not allocate network device\n");
- return -ENOMEM;
- }
-
- pInfo = netdev_priv(netdev);
-
- memset(pInfo, 0, sizeof(struct ft1000_info));
-
- dev_alloc_name(netdev, netdev->name);
-
- pr_debug("network device name is %s\n", netdev->name);
-
- if (strncmp(netdev->name, "eth", 3) == 0) {
- card_nr[0] = netdev->name[3];
- card_nr[1] = '\0';
- ret_val = kstrtou8(card_nr, 10, &gCardIndex);
- if (ret_val) {
- netdev_err(ft1000dev->net, "Can't parse netdev\n");
- goto err_net;
- }
-
- ft1000dev->CardNumber = gCardIndex;
- pr_debug("card number = %d\n", ft1000dev->CardNumber);
- } else {
- netdev_err(ft1000dev->net, "ft1000: Invalid device name\n");
- ret_val = -ENXIO;
- goto err_net;
- }
-
- memset(&pInfo->stats, 0, sizeof(struct net_device_stats));
-
- spin_lock_init(&pInfo->dpram_lock);
- pInfo->priv = ft1000dev;
- pInfo->DrvErrNum = 0;
- pInfo->registered = 1;
- pInfo->ft1000_reset = ft1000_reset;
- pInfo->mediastate = 0;
- pInfo->fifo_cnt = 0;
- ft1000dev->DeviceCreated = FALSE;
- pInfo->CardReady = 0;
- pInfo->DSP_TIME[0] = 0;
- pInfo->DSP_TIME[1] = 0;
- pInfo->DSP_TIME[2] = 0;
- pInfo->DSP_TIME[3] = 0;
- ft1000dev->fAppMsgPend = false;
- ft1000dev->fCondResetPend = false;
- ft1000dev->usbboot = 0;
- ft1000dev->dspalive = 0;
- memset(&ft1000dev->tempbuf[0], 0, sizeof(ft1000dev->tempbuf));
-
- INIT_LIST_HEAD(&pInfo->prov_list);
-
- INIT_LIST_HEAD(&ft1000dev->nodes.list);
-
- netdev->netdev_ops = &ftnet_ops;
-
- ft1000dev->net = netdev;
-
- pr_debug("Initialize free_buff_lock and freercvpool\n");
- spin_lock_init(&free_buff_lock);
-
- /* initialize a list of buffers to be use for queuing
- * up receive command data
- */
- INIT_LIST_HEAD(&freercvpool);
-
- /* create list of free buffers */
- for (i = 0; i < NUM_OF_FREE_BUFFERS; i++) {
- /* Get memory for DPRAM_DATA link list */
- pdpram_blk = kmalloc(sizeof(struct dpram_blk), GFP_KERNEL);
- if (pdpram_blk == NULL) {
- ret_val = -ENOMEM;
- goto err_free;
- }
- /* Get a block of memory to store command data */
- pdpram_blk->pbuffer = kmalloc(MAX_CMD_SQSIZE, GFP_KERNEL);
- if (pdpram_blk->pbuffer == NULL) {
- ret_val = -ENOMEM;
- kfree(pdpram_blk);
- goto err_free;
- }
- /* link provisioning data */
- list_add_tail(&pdpram_blk->list, &freercvpool);
- }
- numofmsgbuf = NUM_OF_FREE_BUFFERS;
-
- return 0;
-
-err_free:
- list_for_each_safe(cur, tmp, &freercvpool) {
- pdpram_blk = list_entry(cur, struct dpram_blk, list);
- list_del(&pdpram_blk->list);
- kfree(pdpram_blk->pbuffer);
- kfree(pdpram_blk);
- }
-err_net:
- free_netdev(netdev);
- return ret_val;
-}
-
-/* register the network driver */
-int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
- struct usb_interface *intf)
-{
- struct net_device *netdev;
- struct ft1000_info *pInfo;
- int rc;
-
- netdev = ft1000dev->net;
- pInfo = netdev_priv(ft1000dev->net);
-
- ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
-
- usb_set_intfdata(intf, pInfo);
- SET_NETDEV_DEV(netdev, &intf->dev);
-
- rc = register_netdev(netdev);
- if (rc) {
- pr_debug("could not register network device\n");
- free_netdev(netdev);
- return rc;
- }
-
- ft1000_create_dev(ft1000dev);
-
- pInfo->CardReady = 1;
-
- return 0;
-}
-
-/* take a packet from the FIFO up link and
- * convert it into an ethernet packet and deliver it to the IP stack
- */
-static int ft1000_copy_up_pkt(struct urb *urb)
-{
- struct ft1000_info *info = urb->context;
- struct ft1000_usb *ft1000dev = info->priv;
- struct net_device *net = ft1000dev->net;
-
- u16 tempword;
- u16 len;
- u16 lena;
- struct sk_buff *skb;
- u16 i;
- u8 *pbuffer = NULL;
- u8 *ptemp = NULL;
- u16 *chksum;
-
- if (ft1000dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- return 0;
- }
- /* Read length */
- len = urb->transfer_buffer_length;
- lena = urb->actual_length;
-
- chksum = (u16 *)ft1000dev->rx_buf;
-
- tempword = *chksum++;
- for (i = 1; i < 7; i++)
- tempword ^= *chksum++;
-
- if (tempword != *chksum) {
- info->stats.rx_errors++;
- ft1000_submit_rx_urb(info);
- return -1;
- }
-
- skb = dev_alloc_skb(len + 12 + 2);
-
- if (skb == NULL) {
- info->stats.rx_errors++;
- ft1000_submit_rx_urb(info);
- return -1;
- }
-
- pbuffer = (u8 *)skb_put(skb, len + 12);
-
- /* subtract the number of bytes read already */
- ptemp = pbuffer;
-
- /* fake MAC address */
- *pbuffer++ = net->dev_addr[0];
- *pbuffer++ = net->dev_addr[1];
- *pbuffer++ = net->dev_addr[2];
- *pbuffer++ = net->dev_addr[3];
- *pbuffer++ = net->dev_addr[4];
- *pbuffer++ = net->dev_addr[5];
- *pbuffer++ = 0x00;
- *pbuffer++ = 0x07;
- *pbuffer++ = 0x35;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xff;
- *pbuffer++ = 0xfe;
-
- memcpy(pbuffer, ft1000dev->rx_buf + sizeof(struct pseudo_hdr),
- len - sizeof(struct pseudo_hdr));
-
- skb->dev = net;
-
- skb->protocol = eth_type_trans(skb, net);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
-
- info->stats.rx_packets++;
- /* Add on 12 bytes for MAC address which was removed */
- info->stats.rx_bytes += (lena + 12);
-
- ft1000_submit_rx_urb(info);
-
- return 0;
-}
-
-
-/* the receiving function of the network driver */
-static int ft1000_submit_rx_urb(struct ft1000_info *info)
-{
- int result;
- struct ft1000_usb *pFt1000Dev = info->priv;
-
- if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
- pr_debug("network driver is closed, return\n");
- return -ENODEV;
- }
-
- usb_fill_bulk_urb(pFt1000Dev->rx_urb,
- pFt1000Dev->dev,
- usb_rcvbulkpipe(pFt1000Dev->dev,
- pFt1000Dev->bulk_in_endpointAddr),
- pFt1000Dev->rx_buf, MAX_BUF_SIZE,
- (usb_complete_t)ft1000_copy_up_pkt, info);
-
- result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC);
-
- if (result) {
- pr_err("submitting rx_urb %d failed\n", result);
- return result;
- }
-
- return 0;
-}
-
-/* close the network driver */
-int ft1000_close(struct net_device *net)
-{
- struct ft1000_info *pInfo = netdev_priv(net);
- struct ft1000_usb *ft1000dev = pInfo->priv;
-
- ft1000dev->status |= FT1000_STATUS_CLOSING;
-
- pr_debug("pInfo=%p, ft1000dev=%p\n", pInfo, ft1000dev);
- netif_carrier_off(net);
- netif_stop_queue(net);
- ft1000dev->status &= ~FT1000_STATUS_CLOSING;
-
- pInfo->ProgConStat = 0xff;
-
- return 0;
-}
-
-/* check if the device is presently available on the system. */
-static int ft1000_chkcard(struct ft1000_usb *dev)
-{
- u16 tempword;
- int status;
-
- if (dev->fCondResetPend) {
- pr_debug("Card is being reset, return FALSE\n");
- return TRUE;
- }
- /* Mask register is used to check for device presence since it is never
- * set to zero.
- */
- status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK);
- if (tempword == 0) {
- pr_debug("IMASK = 0 Card not detected\n");
- return FALSE;
- }
- /* The system will return the value of 0xffff for the version register
- * if the device is not present.
- */
- status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID);
- if (tempword != 0x1b01) {
- dev->status |= FT1000_STATUS_CLOSING;
- pr_debug("Version = 0xffff Card not detected\n");
- return FALSE;
- }
- return TRUE;
-}
-
-/* read a message from the dpram area.
- * Input:
- * dev - network device structure
- * pbuffer - caller supply address to buffer
- */
-static bool ft1000_receive_cmd(struct ft1000_usb *dev, u16 *pbuffer,
- int maxsz)
-{
- u16 size;
- int ret;
- u16 *ppseudohdr;
- int i;
- u16 tempword;
-
- ret =
- ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (u8 *)&size,
- FT1000_MAG_PH_LEN_INDX);
- size = ntohs(size) + PSEUDOSZ;
- if (size > maxsz) {
- pr_debug("Invalid command length = %d\n", size);
- return FALSE;
- }
- ppseudohdr = (u16 *)pbuffer;
- ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE,
- FT1000_REG_DPRAM_ADDR);
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE + 1,
- FT1000_REG_DPRAM_ADDR);
- for (i = 0; i <= (size >> 2); i++) {
- ret =
- ft1000_read_register(dev, pbuffer,
- FT1000_REG_MAG_DPDATAL);
- pbuffer++;
- ret =
- ft1000_read_register(dev, pbuffer,
- FT1000_REG_MAG_DPDATAH);
- pbuffer++;
- }
- /* copy odd aligned word */
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL);
-
- pbuffer++;
- ret =
- ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
-
- pbuffer++;
- if (size & 0x0001) {
- /* copy odd byte from fifo */
- ret =
- ft1000_read_register(dev, &tempword,
- FT1000_REG_DPRAM_DATA);
- *pbuffer = ntohs(tempword);
- }
- /* Check if pseudo header checksum is good
- * Calculate pseudo header checksum
- */
- tempword = *ppseudohdr++;
- for (i = 1; i < 7; i++)
- tempword ^= *ppseudohdr++;
-
- if (tempword != *ppseudohdr)
- return FALSE;
-
- return TRUE;
-}
-
-static int ft1000_dsp_prov(void *arg)
-{
- struct ft1000_usb *dev = (struct ft1000_usb *)arg;
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 tempword;
- u16 len;
- u16 i = 0;
- struct prov_record *ptr;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- int status;
- u16 TempShortBuf[256];
-
- while (list_empty(&info->prov_list) == 0) {
- pr_debug("DSP Provisioning List Entry\n");
-
- /* Check if doorbell is available */
- pr_debug("check if doorbell is cleared\n");
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (status) {
- pr_debug("ft1000_read_register error\n");
- break;
- }
-
- while (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- i++;
- if (i == 10) {
- pr_debug("message drop\n");
- return -1;
- }
- ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- }
-
- if (!(tempword & FT1000_DB_DPRAM_TX)) {
- pr_debug("*** Provision Data Sent to DSP\n");
-
- /* Send provisioning data */
- ptr = list_entry(info->prov_list.next,
- struct prov_record, list);
- len = *(u16 *)ptr->pprov_data;
- len = htons(len);
- len += PSEUDOSZ;
-
- pmsg = (u16 *)ptr->pprov_data;
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- TempShortBuf[0] = 0;
- TempShortBuf[1] = htons(len);
- memcpy(&TempShortBuf[2], ppseudo_hdr, len);
-
- status =
- ft1000_write_dpram32(dev, 0,
- (u8 *)&TempShortBuf[0],
- (unsigned short)(len + 2));
- status =
- ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
-
- list_del(&ptr->list);
- kfree(ptr->pprov_data);
- kfree(ptr);
- }
- usleep_range(9000, 11000);
- }
-
- pr_debug("DSP Provisioning List Entry finished\n");
-
- msleep(100);
-
- dev->fProvComplete = true;
- info->CardReady = 1;
-
- return 0;
-}
-
-static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size)
-{
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 msgtype;
- u16 tempword;
- struct media_msg *pmediamsg;
- struct dsp_init_msg *pdspinitmsg;
- struct drv_msg *pdrvmsg;
- u16 i;
- struct pseudo_hdr *ppseudo_hdr;
- u16 *pmsg;
- int status;
- union {
- u8 byte[2];
- u16 wrd;
- } convert;
-
- char *cmdbuffer = kmalloc(1600, GFP_KERNEL);
-
- if (!cmdbuffer)
- return -ENOMEM;
-
- status = ft1000_read_dpram32(dev, 0x200, cmdbuffer, size);
-
-#ifdef JDEBUG
- print_hex_dump_debug("cmdbuffer: ", HEX_DUMP_OFFSET, 16, 1,
- cmdbuffer, size, true);
-#endif
- pdrvmsg = (struct drv_msg *)&cmdbuffer[2];
- msgtype = ntohs(pdrvmsg->type);
- pr_debug("Command message type = 0x%x\n", msgtype);
- switch (msgtype) {
- case MEDIA_STATE:{
- pr_debug("Command message type = MEDIA_STATE\n");
- pmediamsg = (struct media_msg *)&cmdbuffer[0];
- if (info->ProgConStat != 0xFF) {
- if (pmediamsg->state) {
- pr_debug("Media is up\n");
- if (info->mediastate == 0) {
- if (dev->NetDevRegDone)
- netif_wake_queue(dev->net);
- info->mediastate = 1;
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- if (dev->NetDevRegDone)
- info->ConTm = 0;
- }
- }
- } else {
- pr_debug("Media is down\n");
- if (info->mediastate == 1) {
- info->mediastate = 0;
- info->ConTm = 0;
- }
- }
- break;
- }
- case DSP_INIT_MSG:{
- pr_debug("Command message type = DSP_INIT_MSG\n");
- pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2];
- memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
- pr_debug("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
- info->DspVer[0], info->DspVer[1], info->DspVer[2],
- info->DspVer[3]);
- memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
- HWSERNUMSZ);
- memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
- memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
- pr_debug("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n",
- info->eui64[0], info->eui64[1], info->eui64[2],
- info->eui64[3], info->eui64[4], info->eui64[5],
- info->eui64[6], info->eui64[7]);
- dev->net->dev_addr[0] = info->eui64[0];
- dev->net->dev_addr[1] = info->eui64[1];
- dev->net->dev_addr[2] = info->eui64[2];
- dev->net->dev_addr[3] = info->eui64[5];
- dev->net->dev_addr[4] = info->eui64[6];
- dev->net->dev_addr[5] = info->eui64[7];
-
- if (ntohs(pdspinitmsg->length) ==
- (sizeof(struct dsp_init_msg) - 20)) {
- memcpy(info->ProductMode, pdspinitmsg->ProductMode,
- MODESZ);
- memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, CALVERSZ);
- memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
- CALDATESZ);
- pr_debug("RFCalVer = 0x%2x 0x%2x\n",
- info->RfCalVer[0], info->RfCalVer[1]);
- }
- break;
- }
- case DSP_PROVISION:{
- pr_debug("Command message type = DSP_PROVISION\n");
-
- /* kick off dspprov routine to start provisioning
- * Send provisioning data to DSP
- */
- if (list_empty(&info->prov_list) == 0) {
- dev->fProvComplete = false;
- status = ft1000_dsp_prov(dev);
- if (status != 0)
- goto out;
- } else {
- dev->fProvComplete = true;
- status = ft1000_write_register(dev, FT1000_DB_HB,
- FT1000_REG_DOORBELL);
- pr_debug("No more DSP provisioning data in dsp image\n");
- }
- pr_debug("DSP PROVISION is done\n");
- break;
- }
- case DSP_STORE_INFO:{
- pr_debug("Command message type = DSP_STORE_INFO");
- tempword = ntohs(pdrvmsg->length);
- info->DSPInfoBlklen = tempword;
- if (tempword < (MAX_DSP_SESS_REC - 4)) {
- pmsg = (u16 *)&pdrvmsg->data[0];
- for (i = 0; i < ((tempword + 1) / 2); i++) {
- pr_debug("dsp info data = 0x%x\n", *pmsg);
- info->DSPInfoBlk[i + 10] = *pmsg++;
- }
- } else {
- info->DSPInfoBlklen = 0;
- }
- break;
- }
- case DSP_GET_INFO:{
- pr_debug("Got DSP_GET_INFO\n");
- /* copy dsp info block to dsp */
- dev->DrvMsgPend = 1;
- /* allow any outstanding ioctl to finish */
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- break;
- }
- }
- /* Put message into Slow Queue Form Pseudo header */
- pmsg = (u16 *)info->DSPInfoBlk;
- *pmsg++ = 0;
- *pmsg++ = htons(info->DSPInfoBlklen + 20 + info->DSPInfoBlklen);
- ppseudo_hdr =
- (struct pseudo_hdr *)(u16 *)&info->DSPInfoBlk[2];
- ppseudo_hdr->length = htons(info->DSPInfoBlklen + 4
- + info->DSPInfoBlklen);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- info->DSPInfoBlk[10] = 0x7200;
- info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen);
- status = ft1000_write_dpram32(dev, 0,
- (u8 *)&info->DSPInfoBlk[0],
- (unsigned short)(info->DSPInfoBlklen + 22));
- status = ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
- FT1000_REG_DOORBELL);
- dev->DrvMsgPend = 0;
- break;
- }
- case GET_DRV_ERR_RPT_MSG:{
- pr_debug("Got GET_DRV_ERR_RPT_MSG\n");
- /* copy driver error message to dsp */
- dev->DrvMsgPend = 1;
- /* allow any outstanding ioctl to finish */
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX) {
- mdelay(10);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_DOORBELL);
- if (tempword & FT1000_DB_DPRAM_TX)
- mdelay(10);
- }
- if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
- /* Put message into Slow Queue Form Pseudo header */
- pmsg = (u16 *)&tempbuffer[0];
- ppseudo_hdr = (struct pseudo_hdr *)pmsg;
- ppseudo_hdr->length = htons(0x0012);
- ppseudo_hdr->source = 0x10;
- ppseudo_hdr->destination = 0x20;
- ppseudo_hdr->portdest = 0;
- ppseudo_hdr->portsrc = 0;
- ppseudo_hdr->sh_str_id = 0;
- ppseudo_hdr->control = 0;
- ppseudo_hdr->rsvd1 = 0;
- ppseudo_hdr->rsvd2 = 0;
- ppseudo_hdr->qos_class = 0;
- /* Insert slow queue sequence number */
- ppseudo_hdr->seq_num = info->squeseqnum++;
- /* Insert application id */
- ppseudo_hdr->portsrc = 0;
- /* Calculate new checksum */
- ppseudo_hdr->checksum = *pmsg++;
- for (i = 1; i < 7; i++)
- ppseudo_hdr->checksum ^= *pmsg++;
-
- pmsg = (u16 *)&tempbuffer[16];
- *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
- *pmsg++ = htons(0x000e);
- *pmsg++ = htons(info->DSP_TIME[0]);
- *pmsg++ = htons(info->DSP_TIME[1]);
- *pmsg++ = htons(info->DSP_TIME[2]);
- *pmsg++ = htons(info->DSP_TIME[3]);
- convert.byte[0] = info->DspVer[0];
- convert.byte[1] = info->DspVer[1];
- *pmsg++ = convert.wrd;
- convert.byte[0] = info->DspVer[2];
- convert.byte[1] = info->DspVer[3];
- *pmsg++ = convert.wrd;
- *pmsg++ = htons(info->DrvErrNum);
-
- status = card_send_command(dev,
- (unsigned char *)&tempbuffer[0],
- (u16)(0x0012 + PSEUDOSZ));
- if (status)
- goto out;
- info->DrvErrNum = 0;
- }
- dev->DrvMsgPend = 0;
- break;
- }
- default:
- break;
- }
-
- status = 0;
-out:
- kfree(cmdbuffer);
- return status;
-}
-
-/* Check which application has registered for dsp broadcast messages */
-static int dsp_broadcast_msg_id(struct ft1000_usb *dev)
-{
- struct dpram_blk *pdpram_blk;
- unsigned long flags;
- int i;
-
- for (i = 0; i < MAX_NUM_APP; i++) {
- if ((dev->app_info[i].DspBCMsgFlag)
- && (dev->app_info[i].fileobject)
- && (dev->app_info[i].NumOfMsg
- < MAX_MSG_LIMIT)) {
- pdpram_blk = ft1000_get_buffer(&freercvpool);
- if (pdpram_blk == NULL) {
- pr_debug("Out of memory in free receive command pool\n");
- dev->app_info[i].nRxMsgMiss++;
- return -1;
- }
- if (ft1000_receive_cmd(dev, pdpram_blk->pbuffer,
- MAX_CMD_SQSIZE)) {
- /* Put message into the
- * appropriate application block
- */
- dev->app_info[i].nRxMsg++;
- spin_lock_irqsave(&free_buff_lock, flags);
- list_add_tail(&pdpram_blk->list,
- &dev->app_info[i] .app_sqlist);
- dev->app_info[i].NumOfMsg++;
- spin_unlock_irqrestore(&free_buff_lock, flags);
- wake_up_interruptible(&dev->app_info[i]
- .wait_dpram_msg);
- } else {
- dev->app_info[i].nRxMsgMiss++;
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- pr_debug("ft1000_get_buffer NULL\n");
- return -1;
- }
- }
- }
- return 0;
-}
-
-static int handle_misc_portid(struct ft1000_usb *dev)
-{
- struct dpram_blk *pdpram_blk;
- int i;
-
- pdpram_blk = ft1000_get_buffer(&freercvpool);
- if (pdpram_blk == NULL) {
- pr_debug("Out of memory in free receive command pool\n");
- return -1;
- }
- if (!ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE))
- goto exit_failure;
-
- /* Search for correct application block */
- for (i = 0; i < MAX_NUM_APP; i++) {
- if (dev->app_info[i].app_id == ((struct pseudo_hdr *)
- pdpram_blk->pbuffer)->portdest)
- break;
- }
- if (i == MAX_NUM_APP) {
- pr_debug("No application matching id = %d\n",
- ((struct pseudo_hdr *)pdpram_blk->pbuffer)->portdest);
- goto exit_failure;
- } else if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) {
- goto exit_failure;
- } else {
- dev->app_info[i].nRxMsg++;
- /* Put message into the appropriate application block */
- list_add_tail(&pdpram_blk->list, &dev->app_info[i].app_sqlist);
- dev->app_info[i].NumOfMsg++;
- }
- return 0;
-
-exit_failure:
- ft1000_free_buffer(pdpram_blk, &freercvpool);
- return -1;
-}
-
-int ft1000_poll(void *dev_id)
-{
- struct ft1000_usb *dev = (struct ft1000_usb *)dev_id;
- struct ft1000_info *info = netdev_priv(dev->net);
- u16 tempword;
- int status;
- u16 size;
- int i;
- u16 data;
- u16 modulo;
- u16 portid;
-
- if (ft1000_chkcard(dev) == FALSE) {
- pr_debug("failed\n");
- return -1;
- }
- status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
- if (!status) {
- if (tempword & FT1000_DB_DPRAM_RX) {
- status = ft1000_read_dpram16(dev,
- 0x200, (u8 *)&data, 0);
- size = ntohs(data) + 16 + 2;
- if (size % 4) {
- modulo = 4 - (size % 4);
- size = size + modulo;
- }
- status = ft1000_read_dpram16(dev, 0x201,
- (u8 *)&portid, 1);
- portid &= 0xff;
- if (size < MAX_CMD_SQSIZE) {
- switch (portid) {
- case DRIVERID:
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n");
- status = ft1000_proc_drvmsg(dev, size);
- if (status != 0)
- return status;
- break;
- case DSPBCMSGID:
- status = dsp_broadcast_msg_id(dev);
- break;
- default:
- status = handle_misc_portid(dev);
- break;
- }
- } else
- pr_debug("Invalid total length for SlowQ = %d\n",
- size);
- status = ft1000_write_register(dev,
- FT1000_DB_DPRAM_RX,
- FT1000_REG_DOORBELL);
- } else if (tempword & FT1000_DSP_ASIC_RESET) {
- /* Let's reset the ASIC from the Host side as well */
- status = ft1000_write_register(dev, ASIC_RESET_BIT,
- FT1000_REG_RESET);
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_RESET);
- i = 0;
- while (tempword & ASIC_RESET_BIT) {
- status = ft1000_read_register(dev, &tempword,
- FT1000_REG_RESET);
- usleep_range(9000, 11000);
- i++;
- if (i == 100)
- break;
- }
- if (i == 100) {
- pr_debug("Unable to reset ASIC\n");
- return 0;
- }
- usleep_range(9000, 11000);
- /* Program WMARK register */
- status = ft1000_write_register(dev, 0x600,
- FT1000_REG_MAG_WATERMARK);
- /* clear ASIC reset doorbell */
- status = ft1000_write_register(dev,
- FT1000_DSP_ASIC_RESET,
- FT1000_REG_DOORBELL);
- usleep_range(9000, 11000);
- } else if (tempword & FT1000_ASIC_RESET_REQ) {
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n");
- /* clear ASIC reset request from DSP */
- status = ft1000_write_register(dev,
- FT1000_ASIC_RESET_REQ,
- FT1000_REG_DOORBELL);
- status = ft1000_write_register(dev, HOST_INTF_BE,
- FT1000_REG_SUP_CTRL);
- /* copy dsp session record from Adapter block */
- status = ft1000_write_dpram32(dev, 0,
- (u8 *)&info->DSPSess.Rec[0], 1024);
- status = ft1000_write_register(dev, 0x600,
- FT1000_REG_MAG_WATERMARK);
- /* ring doorbell to tell DSP that
- * ASIC is out of reset
- */
- status = ft1000_write_register(dev,
- FT1000_ASIC_RESET_DSP,
- FT1000_REG_DOORBELL);
- } else if (tempword & FT1000_DB_COND_RESET) {
- pr_debug("FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n");
- if (!dev->fAppMsgPend) {
- /* Reset ASIC and DSP */
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER0,
- (u8 *)&info->DSP_TIME[0],
- FT1000_MAG_DSP_TIMER0_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER1,
- (u8 *)&info->DSP_TIME[1],
- FT1000_MAG_DSP_TIMER1_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER2,
- (u8 *)&info->DSP_TIME[2],
- FT1000_MAG_DSP_TIMER2_INDX);
- status = ft1000_read_dpram16(dev,
- FT1000_MAG_DSP_TIMER3,
- (u8 *)&info->DSP_TIME[3],
- FT1000_MAG_DSP_TIMER3_INDX);
- info->CardReady = 0;
- info->DrvErrNum = DSP_CONDRESET_INFO;
- pr_debug("DSP conditional reset requested\n");
- info->ft1000_reset(dev->net);
- } else {
- dev->fProvComplete = false;
- dev->fCondResetPend = true;
- }
- ft1000_write_register(dev, FT1000_DB_COND_RESET,
- FT1000_REG_DOORBELL);
- }
- }
- return 0;
-}
+++ /dev/null
-/*
- *---------------------------------------------------------------------------
- * FT1000 driver for Flarion Flash OFDM NIC Device
- *
- * Copyright (C) 2002 Flarion Technologies, All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) any
- * later version. This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details. You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place -
- * Suite 330, Boston, MA 02111-1307, USA.
- *---------------------------------------------------------------------------
- *
- * File: ft1000_ioctl.h
- *
- * Description: Common structures and defines relating to IOCTL
- *
- * History:
- * 11/5/02 Whc Created.
- *
- *---------------------------------------------------------------------------
- */
-#ifndef _FT1000IOCTLH_
-#define _FT1000IOCTLH_
-
-struct IOCTL_GET_VER {
- unsigned long drv_ver;
-} __packed;
-
-/* Data structure for Dsp statistics */
-struct IOCTL_GET_DSP_STAT {
- unsigned char DspVer[DSPVERSZ]; /* DSP version number */
- unsigned char HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- unsigned char Sku[SKUSZ]; /* SKU */
- unsigned char eui64[EUISZ]; /* EUI64 */
- unsigned short ConStat; /* Connection Status */
- /* Bits 0-3 = Connection Status Field */
- /* 0000=Idle (Disconnect) */
- /* 0001=Searching */
- /* 0010=Active (Connected) */
- /* 0011=Waiting for L2 down */
- /* 0100=Sleep */
- unsigned short LedStat; /* Led Status */
- /* Bits 0-3 = Signal Strength Field */
- /* 0000 = -105dBm to -92dBm */
- /* 0001 = -92dBm to -85dBm */
- /* 0011 = -85dBm to -75dBm */
- /* 0111 = -75dBm to -50dBm */
- /* 1111 = -50dBm to 0dBm */
- /* Bits 4-7 = Reserved */
- /* Bits 8-11 = SNR Field */
- /* 0000 = <2dB */
- /* 0001 = 2dB to 8dB */
- /* 0011 = 8dB to 15dB */
- /* 0111 = 15dB to 22dB */
- /* 1111 = >22dB */
- /* Bits 12-15 = Reserved */
- unsigned long nTxPkts; /* Number of packets transmitted
- * from host to dsp
- */
- unsigned long nRxPkts; /* Number of packets received from
- * dsp to host
- */
- unsigned long nTxBytes; /* Number of bytes transmitted
- * from host to dsp
- */
- unsigned long nRxBytes; /* Number of bytes received from
- * dsp to host
- */
- unsigned long ConTm; /* Current session connection time
- * in seconds
- */
- unsigned char CalVer[CALVERSZ]; /* Proprietary Calibration
- * Version
- */
- unsigned char CalDate[CALDATESZ]; /* Proprietary Calibration Date */
-} __packed;
-
-/* Data structure for Dual Ported RAM messaging between Host and Dsp */
-struct IOCTL_DPRAM_BLK {
- unsigned short total_len;
- struct pseudo_hdr pseudohdr;
- unsigned char buffer[1780];
-} __packed;
-
-struct IOCTL_DPRAM_COMMAND {
- unsigned short extra;
- struct IOCTL_DPRAM_BLK dpram_blk;
-} __packed;
-
-/*
- * Custom IOCTL command codes
- */
-#define FT1000_MAGIC_CODE 'F'
-
-#define IOCTL_REGISTER_CMD 0
-#define IOCTL_SET_DPRAM_CMD 3
-#define IOCTL_GET_DPRAM_CMD 4
-#define IOCTL_GET_DSP_STAT_CMD 6
-#define IOCTL_GET_VER_CMD 7
-#define IOCTL_CONNECT 10
-#define IOCTL_DISCONNECT 11
-
-#define IOCTL_FT1000_GET_DSP_STAT _IOR(FT1000_MAGIC_CODE, \
- IOCTL_GET_DSP_STAT_CMD, \
- struct IOCTL_GET_DSP_STAT)
-#define IOCTL_FT1000_GET_VER _IOR(FT1000_MAGIC_CODE, IOCTL_GET_VER_CMD, \
- struct IOCTL_GET_VER)
-#define IOCTL_FT1000_CONNECT _IO(FT1000_MAGIC_CODE, IOCTL_CONNECT)
-#define IOCTL_FT1000_DISCONNECT _IO(FT1000_MAGIC_CODE, IOCTL_DISCONNECT)
-#define IOCTL_FT1000_SET_DPRAM _IOW(FT1000_MAGIC_CODE, IOCTL_SET_DPRAM_CMD, \
- struct IOCTL_DPRAM_BLK)
-#define IOCTL_FT1000_GET_DPRAM _IOR(FT1000_MAGIC_CODE, IOCTL_GET_DPRAM_CMD, \
- struct IOCTL_DPRAM_BLK)
-#define IOCTL_FT1000_REGISTER _IOW(FT1000_MAGIC_CODE, IOCTL_REGISTER_CMD, \
- unsigned short *)
-
-#endif /* _FT1000IOCTLH_ */
+++ /dev/null
-/*=====================================================
- * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
- *
- *
- * This file is part of Express Card USB Driver
- *====================================================
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/firmware.h>
-#include "ft1000_usb.h"
-
-#include <linux/kthread.h>
-
-MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER");
-MODULE_LICENSE("Dual MPL/GPL");
-MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards");
-
-void *pFileStart;
-size_t FileLength;
-
-#define VENDOR_ID 0x1291 /* Qualcomm vendor id */
-#define PRODUCT_ID 0x11 /* fake product id */
-
-/* table of devices that work with this driver */
-static struct usb_device_id id_table[] = {
- {USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
- {},
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static bool gPollingfailed;
-static int ft1000_poll_thread(void *arg)
-{
- int ret;
-
- while (!kthread_should_stop()) {
- usleep_range(10000, 11000);
- if (!gPollingfailed) {
- ret = ft1000_poll(arg);
- if (ret != 0) {
- pr_debug("polling failed\n");
- gPollingfailed = true;
- }
- }
- }
- return 0;
-}
-
-static int ft1000_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- struct usb_device *dev;
- unsigned numaltsetting;
- int i, ret = 0, size;
-
- struct ft1000_usb *ft1000dev;
- struct ft1000_info *pft1000info = NULL;
- const struct firmware *dsp_fw;
-
- ft1000dev = kzalloc(sizeof(struct ft1000_usb), GFP_KERNEL);
- if (!ft1000dev)
- return -ENOMEM;
-
- dev = interface_to_usbdev(interface);
- pr_debug("usb device descriptor info - number of configuration is %d\n",
- dev->descriptor.bNumConfigurations);
-
- ft1000dev->dev = dev;
- ft1000dev->status = 0;
- ft1000dev->net = NULL;
- ft1000dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- ft1000dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ft1000dev->tx_urb || !ft1000dev->rx_urb) {
- ret = -ENOMEM;
- goto err_fw;
- }
-
- numaltsetting = interface->num_altsetting;
- pr_debug("number of alt settings is: %d\n", numaltsetting);
- iface_desc = interface->cur_altsetting;
- pr_debug("number of endpoints is: %d\n",
- iface_desc->desc.bNumEndpoints);
- pr_debug("descriptor type is: %d\n", iface_desc->desc.bDescriptorType);
- pr_debug("interface number is: %d\n",
- iface_desc->desc.bInterfaceNumber);
- pr_debug("alternatesetting is: %d\n",
- iface_desc->desc.bAlternateSetting);
- pr_debug("interface class is: %d\n", iface_desc->desc.bInterfaceClass);
- pr_debug("control endpoint info:\n");
- pr_debug("descriptor0 type -- %d\n",
- iface_desc->endpoint[0].desc.bmAttributes);
- pr_debug("descriptor1 type -- %d\n",
- iface_desc->endpoint[1].desc.bmAttributes);
- pr_debug("descriptor2 type -- %d\n",
- iface_desc->endpoint[2].desc.bmAttributes);
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- endpoint =
- (struct usb_endpoint_descriptor *)&iface_desc->
- endpoint[i].desc;
- pr_debug("endpoint %d\n", i);
- pr_debug("bEndpointAddress=%x, bmAttributes=%x\n",
- endpoint->bEndpointAddress, endpoint->bmAttributes);
- if (usb_endpoint_is_bulk_in(endpoint)) {
- ft1000dev->bulk_in_endpointAddr =
- endpoint->bEndpointAddress;
- pr_debug("in: %d\n", endpoint->bEndpointAddress);
- }
-
- if (usb_endpoint_is_bulk_in(endpoint)) {
- ft1000dev->bulk_out_endpointAddr =
- endpoint->bEndpointAddress;
- pr_debug("out: %d\n", endpoint->bEndpointAddress);
- }
- }
-
- pr_debug("bulk_in=%d, bulk_out=%d\n",
- ft1000dev->bulk_in_endpointAddr,
- ft1000dev->bulk_out_endpointAddr);
-
- ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev);
- if (ret < 0) {
- dev_err(interface->usb_dev, "Error request_firmware()\n");
- goto err_fw;
- }
-
- size = max_t(uint, dsp_fw->size, 4096);
- pFileStart = kmalloc(size, GFP_KERNEL);
-
- if (!pFileStart) {
- release_firmware(dsp_fw);
- ret = -ENOMEM;
- goto err_fw;
- }
-
- memcpy(pFileStart, dsp_fw->data, dsp_fw->size);
- FileLength = dsp_fw->size;
- release_firmware(dsp_fw);
-
- pr_debug("start downloading dsp image...\n");
-
- ret = init_ft1000_netdev(ft1000dev);
- if (ret)
- goto err_load;
-
- pft1000info = netdev_priv(ft1000dev->net);
-
- pr_debug("pft1000info=%p\n", pft1000info);
- ret = dsp_reload(ft1000dev);
- if (ret) {
- dev_err(interface->usb_dev,
- "Problem with DSP image loading\n");
- goto err_load;
- }
-
- gPollingfailed = false;
- ft1000dev->pPollThread =
- kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll");
-
- if (IS_ERR(ft1000dev->pPollThread)) {
- ret = PTR_ERR(ft1000dev->pPollThread);
- goto err_load;
- }
-
- msleep(500);
-
- while (!pft1000info->CardReady) {
- if (gPollingfailed) {
- ret = -EIO;
- goto err_thread;
- }
- msleep(100);
- pr_debug("Waiting for Card Ready\n");
- }
-
- pr_debug("Card Ready!!!! Registering network device\n");
-
- ret = reg_ft1000_netdev(ft1000dev, interface);
- if (ret)
- goto err_thread;
-
- ft1000dev->NetDevRegDone = 1;
-
- return 0;
-
-err_thread:
- kthread_stop(ft1000dev->pPollThread);
-err_load:
- kfree(pFileStart);
-err_fw:
- usb_free_urb(ft1000dev->rx_urb);
- usb_free_urb(ft1000dev->tx_urb);
- kfree(ft1000dev);
- return ret;
-}
-
-static void ft1000_disconnect(struct usb_interface *interface)
-{
- struct ft1000_info *pft1000info;
- struct ft1000_usb *ft1000dev;
-
- pft1000info = (struct ft1000_info *)usb_get_intfdata(interface);
- pr_debug("In disconnect pft1000info=%p\n", pft1000info);
-
- if (pft1000info) {
- ft1000dev = pft1000info->priv;
- if (ft1000dev->pPollThread)
- kthread_stop(ft1000dev->pPollThread);
-
- pr_debug("threads are terminated\n");
-
- if (ft1000dev->net) {
- pr_debug("destroy char driver\n");
- ft1000_destroy_dev(ft1000dev->net);
- unregister_netdev(ft1000dev->net);
- pr_debug("network device unregistered\n");
- free_netdev(ft1000dev->net);
-
- }
-
- usb_free_urb(ft1000dev->rx_urb);
- usb_free_urb(ft1000dev->tx_urb);
-
- pr_debug("urb freed\n");
-
- kfree(ft1000dev);
- }
- kfree(pFileStart);
-}
-
-static struct usb_driver ft1000_usb_driver = {
- .name = "ft1000usb",
- .probe = ft1000_probe,
- .disconnect = ft1000_disconnect,
- .id_table = id_table,
-};
-
-module_usb_driver(ft1000_usb_driver);
+++ /dev/null
-#ifndef _FT1000_USB_H_
-#define _FT1000_USB_H_
-
-#include "../ft1000.h"
-#include "ft1000_ioctl.h"
-#define FT1000_DRV_VER 0x01010403
-
-#define MAX_NUM_APP 6
-#define MAX_MSG_LIMIT 200
-#define NUM_OF_FREE_BUFFERS 1500
-
-#define PSEUDOSZ 16
-
-struct app_info_block {
- u32 nTxMsg; /* DPRAM msg sent to DSP with app_id */
- u32 nRxMsg; /* DPRAM msg rcv from dsp with app_id */
- u32 nTxMsgReject; /* DPRAM msg rejected due to DSP doorbell
- * set
- */
- u32 nRxMsgMiss; /* DPRAM msg dropped due to overflow */
- struct fown_struct *fileobject;/* Application's file object */
- u16 app_id; /* Application id */
- int DspBCMsgFlag;
- int NumOfMsg; /* number of messages queued up */
- wait_queue_head_t wait_dpram_msg;
- struct list_head app_sqlist; /* link list of msgs for applicaton on
- * slow queue
- */
-} __packed;
-
-#define FALSE 0
-#define TRUE 1
-
-#define FT1000_STATUS_CLOSING 0x01
-
-#define DSPBCMSGID 0x10
-
-/* Electrabuzz specific DPRAM mapping */
-/* this is used by ft1000_usb driver - isn't that a bug? */
-#undef FT1000_DPRAM_RX_BASE
-#define FT1000_DPRAM_RX_BASE 0x1800 /* RX AREA (SlowQ) */
-
-/* MEMORY MAP FOR MAGNEMITE */
-/* the indexes are swapped comparing to PCMCIA - is it OK or a bug? */
-#undef FT1000_MAG_DSP_LED_INDX
-#define FT1000_MAG_DSP_LED_INDX 0x1 /* dsp led status for PAD
- * device
- */
-#undef FT1000_MAG_DSP_CON_STATE_INDX
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x0 /* DSP Connection Status Info */
-
-/* Maximum times trying to get ASIC out of reset */
-#define MAX_ASIC_RESET_CNT 20
-
-#define MAX_BUF_SIZE 4096
-
-struct ft1000_debug_dirs {
- struct list_head list;
- struct dentry *dent;
- struct dentry *file;
- int int_number;
-};
-
-struct ft1000_usb {
- struct usb_device *dev;
- struct net_device *net;
-
- u32 status;
-
- struct urb *rx_urb;
- struct urb *tx_urb;
-
- u8 tx_buf[MAX_BUF_SIZE];
- u8 rx_buf[MAX_BUF_SIZE];
-
- u8 bulk_in_endpointAddr;
- u8 bulk_out_endpointAddr;
-
- struct task_struct *pPollThread;
- unsigned char fcodeldr;
- unsigned char bootmode;
- unsigned char usbboot;
- unsigned short dspalive;
- bool fProvComplete;
- bool fCondResetPend;
- bool fAppMsgPend;
- int DeviceCreated;
- int NetDevRegDone;
- u8 CardNumber;
- u8 DeviceName[15];
- struct ft1000_debug_dirs nodes;
- spinlock_t fifo_lock;
- int appcnt;
- struct app_info_block app_info[MAX_NUM_APP];
- u16 DrvMsgPend;
- unsigned short tempbuf[32];
-} __packed;
-
-
-struct dpram_blk {
- struct list_head list;
- u16 *pbuffer;
-} __packed;
-
-int ft1000_read_register(struct ft1000_usb *ft1000dev,
- u16 *Data, u16 nRegIndx);
-int ft1000_write_register(struct ft1000_usb *ft1000dev,
- u16 value, u16 nRegIndx);
-int ft1000_read_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u16 cnt);
-int ft1000_write_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u16 cnt);
-int ft1000_read_dpram16(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer, u8 highlow);
-int ft1000_write_dpram16(struct ft1000_usb *ft1000dev,
- u16 indx, u16 value, u8 highlow);
-int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer);
-int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev,
- u16 indx, u8 *buffer);
-
-extern void *pFileStart;
-extern size_t FileLength;
-extern int numofmsgbuf;
-
-int ft1000_close(struct net_device *dev);
-int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
- u32 FileLength);
-
-extern struct list_head freercvpool;
-
-/* lock to arbitrate free buffer list for receive command data */
-extern spinlock_t free_buff_lock;
-
-int ft1000_create_dev(struct ft1000_usb *dev);
-void ft1000_destroy_dev(struct net_device *dev);
-int card_send_command(struct ft1000_usb *ft1000dev,
- void *ptempbuffer, int size);
-
-struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
-void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
-
-int dsp_reload(struct ft1000_usb *ft1000dev);
-int init_ft1000_netdev(struct ft1000_usb *ft1000dev);
-struct usb_interface;
-int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
- struct usb_interface *intf);
-int ft1000_poll(void *dev_id);
-
-#endif /* _FT1000_USB_H_ */
+++ /dev/null
-/*
- * Common structures and definitions for FT1000 Flarion Flash OFDM PCMCIA and
- * USB devices.
- *
- * Originally copyright (c) 2002 Flarion Technologies
- *
- */
-
-#define DSPVERSZ 4
-#define HWSERNUMSZ 16
-#define SKUSZ 20
-#define EUISZ 8
-#define MODESZ 2
-#define CALVERSZ 2
-#define CALDATESZ 6
-
-#define ELECTRABUZZ_ID 0 /* ASIC ID for Electrabuzz */
-#define MAGNEMITE_ID 0x1a01 /* ASIC ID for Magnemite */
-
-/* MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE */
-#define FT1000_REG_DPRAM_ADDR 0x000E /* DPADR - Dual Port Ram Indirect
- * Address Register
- */
-#define FT1000_REG_SUP_CTRL 0x0020 /* HCTR - Host Control Register */
-#define FT1000_REG_SUP_STAT 0x0022 /* HSTAT - Host Status Register */
-#define FT1000_REG_RESET 0x0024 /* HCTR - Host Control Register */
-#define FT1000_REG_SUP_ISR 0x0026 /* HISR - Host Interrupt Status
- * Register
- */
-#define FT1000_REG_SUP_IMASK 0x0028 /* HIMASK - Host Interrupt Mask */
-#define FT1000_REG_DOORBELL 0x002a /* DBELL - Door Bell Register */
-#define FT1000_REG_ASIC_ID 0x002e /* ASICID - ASIC Identification
- * Number
- */
-
-/* MEMORY MAP FOR ELECTRABUZZ ASIC */
-#define FT1000_REG_UFIFO_STAT 0x0000 /* UFSR - Uplink FIFO status register */
-#define FT1000_REG_UFIFO_BEG 0x0002 /* UFBR - Uplink FIFO beginning
- * register
- */
-#define FT1000_REG_UFIFO_MID 0x0004 /* UFMR - Uplink FIFO middle register */
-#define FT1000_REG_UFIFO_END 0x0006 /* UFER - Uplink FIFO end register */
-#define FT1000_REG_DFIFO_STAT 0x0008 /* DFSR - Downlink FIFO status
- * register
- */
-#define FT1000_REG_DFIFO 0x000A /* DFR - Downlink FIFO Register */
-#define FT1000_REG_DPRAM_DATA 0x000C /* DPRAM - Dual Port Indirect
- * Data Register
- */
-#define FT1000_REG_WATERMARK 0x0010 /* WMARK - Watermark Register */
-
-/* MEMORY MAP FOR MAGNEMITE */
-#define FT1000_REG_MAG_UFDR 0x0000 /* UFDR - Uplink FIFO Data
- * Register (32-bits)
- */
-#define FT1000_REG_MAG_UFDRL 0x0000 /* UFDRL - Uplink FIFO Data
- * Register low-word (16-bits)
- */
-#define FT1000_REG_MAG_UFDRH 0x0002 /* UFDRH - Uplink FIFO Data Register
- * high-word (16-bits)
- */
-#define FT1000_REG_MAG_UFER 0x0004 /* UFER - Uplink FIFO End Register */
-#define FT1000_REG_MAG_UFSR 0x0006 /* UFSR - Uplink FIFO Status Register */
-#define FT1000_REG_MAG_DFR 0x0008 /* DFR - Downlink FIFO Register
- * (32-bits)
- */
-#define FT1000_REG_MAG_DFRL 0x0008 /* DFRL - Downlink FIFO Register
- * low-word (16-bits)
- */
-#define FT1000_REG_MAG_DFRH 0x000a /* DFRH - Downlink FIFO Register
- * high-word (16-bits)
- */
-#define FT1000_REG_MAG_DFSR 0x000c /* DFSR - Downlink FIFO Status
- * Register
- */
-#define FT1000_REG_MAG_DPDATA 0x0010 /* DPDATA - Dual Port RAM Indirect
- * Data Register (32-bits)
- */
-#define FT1000_REG_MAG_DPDATAL 0x0010 /* DPDATAL - Dual Port RAM Indirect
- * Data Register low-word (16-bits)
- */
-#define FT1000_REG_MAG_DPDATAH 0x0012 /* DPDATAH - Dual Port RAM Indirect Data
- * Register high-word (16-bits)
- */
-#define FT1000_REG_MAG_WATERMARK 0x002c /* WMARK - Watermark Register */
-#define FT1000_REG_MAG_VERSION 0x0030 /* LLC Version */
-
-/* Reserved Dual Port RAM offsets for Electrabuzz */
-#define FT1000_DPRAM_TX_BASE 0x0002 /* Host to PC Card Messaging Area */
-#define FT1000_DPRAM_RX_BASE 0x0800 /* PC Card to Host Messaging Area */
-#define FT1000_FIFO_LEN 0x07FC /* total length for DSP FIFO tracking */
-#define FT1000_HI_HO 0x07FE /* heartbeat with HI/HO */
-#define FT1000_DSP_STATUS 0x0FFE /* dsp status - non-zero is a request
- * to reset dsp
- */
-#define FT1000_DSP_LED 0x0FFA /* dsp led status for PAD device */
-#define FT1000_DSP_CON_STATE 0x0FF8 /* DSP Connection Status Info */
-#define FT1000_DPRAM_FEFE 0x0002 /* location for dsp ready indicator */
-#define FT1000_DSP_TIMER0 0x1FF0 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER1 0x1FF2 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER2 0x1FF4 /* Timer Field from Basestation */
-#define FT1000_DSP_TIMER3 0x1FF6 /* Timer Field from Basestation */
-
-/* Reserved Dual Port RAM offsets for Magnemite */
-#define FT1000_DPRAM_MAG_TX_BASE 0x0000 /* Host to PC Card
- * Messaging Area
- */
-#define FT1000_DPRAM_MAG_RX_BASE 0x0200 /* PC Card to Host
- * Messaging Area
- */
-
-#define FT1000_MAG_FIFO_LEN 0x1FF /* total length for DSP
- * FIFO tracking
- */
-#define FT1000_MAG_FIFO_LEN_INDX 0x1 /* low-word index */
-#define FT1000_MAG_HI_HO 0x1FF /* heartbeat with HI/HO */
-#define FT1000_MAG_HI_HO_INDX 0x0 /* high-word index */
-#define FT1000_MAG_DSP_LED 0x3FE /* dsp led status for
- * PAD device
- */
-#define FT1000_MAG_DSP_LED_INDX 0x0 /* dsp led status for
- * PAD device
- */
-#define FT1000_MAG_DSP_CON_STATE 0x3FE /* DSP Connection Status Info */
-#define FT1000_MAG_DSP_CON_STATE_INDX 0x1 /* DSP Connection Status Info */
-#define FT1000_MAG_DPRAM_FEFE 0x000 /* location for dsp ready
- * indicator
- */
-#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 /* location for dsp ready
- * indicator
- */
-#define FT1000_MAG_DSP_TIMER0 0x3FC /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER0_INDX 0x1
-#define FT1000_MAG_DSP_TIMER1 0x3FC /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER1_INDX 0x0
-#define FT1000_MAG_DSP_TIMER2 0x3FD /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER2_INDX 0x1
-#define FT1000_MAG_DSP_TIMER3 0x3FD /* Timer Field from
- * Basestation
- */
-#define FT1000_MAG_DSP_TIMER3_INDX 0x0
-#define FT1000_MAG_TOTAL_LEN 0x200
-#define FT1000_MAG_TOTAL_LEN_INDX 0x1
-#define FT1000_MAG_PH_LEN 0x200
-#define FT1000_MAG_PH_LEN_INDX 0x0
-#define FT1000_MAG_PORT_ID 0x201
-#define FT1000_MAG_PORT_ID_INDX 0x0
-
-#define HOST_INTF_LE 0x0 /* Host interface little endian mode */
-#define HOST_INTF_BE 0x1 /* Host interface big endian mode */
-
-/* FT1000 to Host Doorbell assignments */
-#define FT1000_DB_DPRAM_RX 0x0001 /* this value indicates that DSP
- * has data for host in DPRAM
- */
-#define FT1000_DB_DNLD_RX 0x0002 /* Downloader handshake doorbell */
-#define FT1000_ASIC_RESET_REQ 0x0004 /* DSP requesting host to
- * reset the ASIC
- */
-#define FT1000_DSP_ASIC_RESET 0x0008 /* DSP indicating host that
- * it will reset the ASIC
- */
-#define FT1000_DB_COND_RESET 0x0010 /* DSP request for a card reset. */
-
-/* Host to FT1000 Doorbell assignments */
-#define FT1000_DB_DPRAM_TX 0x0100 /* this value indicates that host
- * has data for DSP in DPRAM.
- */
-#define FT1000_DB_DNLD_TX 0x0200 /* Downloader handshake doorbell */
-#define FT1000_ASIC_RESET_DSP 0x0400 /* Responds to FT1000_ASIC_RESET_REQ */
-#define FT1000_DB_HB 0x1000 /* Indicates that supervisor has a
- * heartbeat message for DSP.
- */
-
-#define hi 0x6869 /* PC Card heartbeat values */
-#define ho 0x686f /* PC Card heartbeat values */
-
-/* Magnemite specific defines */
-#define hi_mag 0x6968 /* Byte swap hi to avoid
- * additional system call
- */
-#define ho_mag 0x6f68 /* Byte swap ho to avoid
- * additional system call
- */
-
-/* Bit field definitions for Host Interrupt Status Register */
-/* Indicate the cause of an interrupt. */
-#define ISR_EMPTY 0x00 /* no bits set */
-#define ISR_DOORBELL_ACK 0x01 /* Doorbell acknowledge from DSP */
-#define ISR_DOORBELL_PEND 0x02 /* Doorbell pending from DSP */
-#define ISR_RCV 0x04 /* Packet available in Downlink FIFO */
-#define ISR_WATERMARK 0x08 /* Watermark requirements satisfied */
-
-/* Bit field definition for Host Interrupt Mask */
-#define ISR_MASK_NONE 0x0000 /* no bits set */
-#define ISR_MASK_DOORBELL_ACK 0x0001 /* Doorbell acknowledge mask */
-#define ISR_MASK_DOORBELL_PEND 0x0002 /* Doorbell pending mask */
-#define ISR_MASK_RCV 0x0004 /* Downlink Packet available mask */
-#define ISR_MASK_WATERMARK 0x0008 /* Watermark interrupt mask */
-#define ISR_MASK_ALL 0xffff /* Mask all interrupts */
-/* Default interrupt mask
- * (Enable Doorbell pending and Packet available interrupts)
- */
-#define ISR_DEFAULT_MASK 0x7ff9
-
-/* Bit field definition for Host Control Register */
-#define DSP_RESET_BIT 0x0001 /* Bit field to control
- * dsp reset state
- */
- /* (0 = out of reset 1 = reset) */
-#define ASIC_RESET_BIT 0x0002 /* Bit field to control
- * ASIC reset state
- */
- /* (0 = out of reset 1 = reset) */
-#define DSP_UNENCRYPTED 0x0004
-#define DSP_ENCRYPTED 0x0008
-#define EFUSE_MEM_DISABLE 0x0040
-
-/* Application specific IDs */
-#define DSPID 0x20
-#define HOSTID 0x10
-#define DSPAIRID 0x90
-#define DRIVERID 0x00
-#define NETWORKID 0x20
-
-/* Size of DPRAM Message */
-#define MAX_CMD_SQSIZE 1780
-
-#define ENET_MAX_SIZE 1514
-#define ENET_HEADER_SIZE 14
-
-#define SLOWQ_TYPE 0
-#define FASTQ_TYPE 1
-
-#define MAX_DSP_SESS_REC 1024
-
-#define DSP_QID_OFFSET 4
-
-/* Driver message types */
-#define MEDIA_STATE 0x0010
-#define TIME_UPDATE 0x0020
-#define DSP_PROVISION 0x0030
-#define DSP_INIT_MSG 0x0050
-#define DSP_HIBERNATE 0x0060
-#define DSP_STORE_INFO 0x0070
-#define DSP_GET_INFO 0x0071
-#define GET_DRV_ERR_RPT_MSG 0x0073
-#define RSP_DRV_ERR_RPT_MSG 0x0074
-
-/* Driver Error Messages for DSP */
-#define DSP_HB_INFO 0x7ef0
-#define DSP_FIFO_INFO 0x7ef1
-#define DSP_CONDRESET_INFO 0x7ef2
-#define DSP_CMDLEN_INFO 0x7ef3
-#define DSP_CMDPHCKSUM_INFO 0x7ef4
-#define DSP_PKTPHCKSUM_INFO 0x7ef5
-#define DSP_PKTLEN_INFO 0x7ef6
-#define DSP_USER_RESET 0x7ef7
-#define FIFO_FLUSH_MAXLIMIT 0x7ef8
-#define FIFO_FLUSH_BADCNT 0x7ef9
-#define FIFO_ZERO_LEN 0x7efa
-
-/* Pseudo Header structure */
-struct pseudo_hdr {
- unsigned short length; /* length of msg body */
- unsigned char source; /* hardware source id */
- /* Host = 0x10 */
- /* Dsp = 0x20 */
- unsigned char destination; /* hardware destination id
- * (refer to source)
- */
- unsigned char portdest; /* software destination port id */
- /* Host = 0x00 */
- /* Applicaton Broadcast = 0x10 */
- /* Network Stack = 0x20 */
- /* Dsp OAM = 0x80 */
- /* Dsp Airlink = 0x90 */
- /* Dsp Loader = 0xa0 */
- /* Dsp MIP = 0xb0 */
- unsigned char portsrc; /* software source port id
- * (refer to portdest)
- */
- unsigned short sh_str_id; /* not used */
- unsigned char control; /* not used */
- unsigned char rsvd1;
- unsigned char seq_num; /* message sequence number */
- unsigned char rsvd2;
- unsigned short qos_class; /* not used */
- unsigned short checksum; /* pseudo header checksum */
-} __packed;
-
-struct drv_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 data[0];
-} __packed;
-
-struct media_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u16 state;
- u32 ip_addr;
- u32 net_mask;
- u32 gateway;
- u32 dns_1;
- u32 dns_2;
-} __packed;
-
-struct dsp_init_msg {
- struct pseudo_hdr pseudo;
- u16 type;
- u16 length;
- u8 DspVer[DSPVERSZ]; /* DSP version number */
- u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- u8 Sku[SKUSZ]; /* SKU */
- u8 eui64[EUISZ]; /* EUI64 */
- u8 ProductMode[MODESZ]; /* Product Mode (Market/Production) */
- u8 RfCalVer[CALVERSZ]; /* Rf Calibration version */
- u8 RfCalDate[CALDATESZ]; /* Rf Calibration date */
-} __packed;
-
-struct prov_record {
- struct list_head list;
- u8 *pprov_data;
-};
-
-struct ft1000_info {
- void *priv;
- struct net_device_stats stats;
- u16 DrvErrNum;
- u16 AsicID;
- int CardReady;
- int registered;
- int mediastate;
- u8 squeseqnum; /* sequence number on slow queue */
- spinlock_t dpram_lock;
- u16 fifo_cnt;
- u8 DspVer[DSPVERSZ]; /* DSP version number */
- u8 HwSerNum[HWSERNUMSZ]; /* Hardware Serial Number */
- u8 Sku[SKUSZ]; /* SKU */
- u8 eui64[EUISZ]; /* EUI64 */
- time_t ConTm; /* Connection Time */
- u8 ProductMode[MODESZ];
- u8 RfCalVer[CALVERSZ];
- u8 RfCalDate[CALDATESZ];
- u16 DSP_TIME[4];
- u16 LedStat;
- u16 ConStat;
- u16 ProgConStat;
- struct list_head prov_list;
- u16 DSPInfoBlklen;
- int (*ft1000_reset)(void *);
- u16 DSPInfoBlk[MAX_DSP_SESS_REC];
- union {
- u16 Rec[MAX_DSP_SESS_REC];
- u32 MagRec[MAX_DSP_SESS_REC/2];
- } DSPSess;
-};