From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- .../drivers/staging/ft1000/ft1000-pcmcia/Makefile | 2 - kernel/drivers/staging/ft1000/ft1000-pcmcia/boot.h | 158 -- .../drivers/staging/ft1000/ft1000-pcmcia/ft1000.h | 71 - .../staging/ft1000/ft1000-pcmcia/ft1000.img | Bin 305770 -> 0 bytes .../staging/ft1000/ft1000-pcmcia/ft1000_cs.c | 158 -- .../staging/ft1000/ft1000-pcmcia/ft1000_dnld.c | 769 -------- .../staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 2068 -------------------- 7 files changed, 3226 deletions(-) delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/Makefile delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/boot.h delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c delete mode 100644 kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c (limited to 'kernel/drivers/staging/ft1000/ft1000-pcmcia') diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/Makefile b/kernel/drivers/staging/ft1000/ft1000-pcmcia/Makefile deleted file mode 100644 index 715de3f00..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o -ft1000_pcmcia-y := ft1000_hw.o ft1000_dnld.o ft1000_cs.o diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/kernel/drivers/staging/ft1000/ft1000-pcmcia/boot.h deleted file mode 100644 index e4a698528..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/boot.h +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------- - 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 diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h deleted file mode 100644 index 5992670f7..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------------- - 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; -extern struct net_device *init_ft1000_card(struct pcmcia_device *link, - void *ft1000_reset); -extern void stop_ft1000_card(struct net_device *dev); -extern int card_download(struct net_device *dev, const u8 *pFileStart, - size_t FileLength); - -extern u16 ft1000_read_dpram(struct net_device *dev, int offset); -extern void card_bootload(struct net_device *dev); -extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, - int Index); -extern 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 diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img b/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img deleted file mode 100644 index aad3c80d0..000000000 Binary files a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img and /dev/null differ diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c deleted file mode 100644 index e5cc5bedf..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c +++ /dev/null @@ -1,158 +0,0 @@ -/*--------------------------------------------------------------------------- - 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 - . 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 -#include -#include -#include -#include -#include - -/*====================================================================*/ - -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); diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c deleted file mode 100644 index 83683e9a1..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c +++ /dev/null @@ -1,769 +0,0 @@ -/*--------------------------------------------------------------------------- - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - -u16 get_handshake(struct net_device *dev, u16 expected_value); -void put_handshake(struct net_device *dev, u16 handshake_value); -u16 get_request_type(struct net_device *dev); -long get_request_value(struct net_device *dev); -void put_request_value(struct net_device *dev, long lvalue); -u16 hdr_checksum(struct pseudo_hdr *pHdr); - -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); -} - -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; - -} - -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 */ - } -} - -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; - -} - -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; - -} - -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 */ - } - -} - -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; - -} diff --git a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c deleted file mode 100644 index eecfa3770..000000000 --- a/kernel/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ /dev/null @@ -1,2068 +0,0 @@ -/*--------------------------------------------------------------------------- - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#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; -} -- cgit 1.2.3-korg