Staging: Add support for Flarion OFDM usb and pcmcia devices.
This drivers add support for following devices: (usb)-> Qleadtek FLASH-OFDM USB Modem [LR7F04] -> Qleadtek Express Card -> Leadtek Multi-band modem HSDPA Sources for usb: https://sourceforge.net/projects/ft1000/files/ft1000_usb/ft1000_usb_v01.04.tar.gz/download (pcmcia) -> Multimedia Net Card Sources for pcmcia : https://sourceforge.net/projects/ft1000/files/ft1000_pcmcia_2.6.30-2.6.31.tgz/download More informations (in Slovak language): http://ft1000.qintec.sk/home.html Signed-off-by: Marek Belisko <marek.belisko@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
027360c564
commit
f7c1be0cca
@ -165,5 +165,7 @@ source "drivers/staging/keucr/Kconfig"
|
||||
|
||||
source "drivers/staging/bcm/Kconfig"
|
||||
|
||||
source "drivers/staging/ft1000/Kconfig"
|
||||
|
||||
endif # !STAGING_EXCLUDE_BUILD
|
||||
endif # STAGING
|
||||
|
@ -63,3 +63,4 @@ obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
|
||||
obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/
|
||||
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
|
||||
obj-$(CONFIG_BCM_WIMAX) += bcm/
|
||||
obj-$(CONFIG_FT1000) += ft1000/
|
||||
|
22
drivers/staging/ft1000/Kconfig
Normal file
22
drivers/staging/ft1000/Kconfig
Normal file
@ -0,0 +1,22 @@
|
||||
config FT1000
|
||||
tristate "Drivers for Flarion ft1000 devices"
|
||||
|
||||
if FT1000
|
||||
|
||||
config FT1000_USB
|
||||
tristate "Driver for ft1000 usb devices."
|
||||
depends on USB
|
||||
depends on NET
|
||||
help
|
||||
Say Y if you want to have support for Qleadtek FLASH-OFDM USB Modem [LR7F04],
|
||||
Qleadtek Express Card or Leadtek Multi-band modem HSDPA.
|
||||
|
||||
config FT1000_PCMCIA
|
||||
tristate "Driver for ft1000 pcmcia device."
|
||||
depends on PCMCIA
|
||||
depends on NET
|
||||
help
|
||||
Say Y if you want to have support for Flarion card also called
|
||||
Multimedia Net Card.
|
||||
|
||||
endif
|
3
drivers/staging/ft1000/Makefile
Normal file
3
drivers/staging/ft1000/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-$(CONFIG_FT1000_USB) += ft1000-usb/
|
||||
obj-$(CONFIG_FT1000_PCMCIA) += ft1000-pcmcia/
|
||||
|
9
drivers/staging/ft1000/TODO
Normal file
9
drivers/staging/ft1000/TODO
Normal file
@ -0,0 +1,9 @@
|
||||
TODO:
|
||||
- checkpatch.pl cleanups
|
||||
- coding style
|
||||
- sparse fixes
|
||||
- adapt to latest usb and pcmcia api changes
|
||||
- change firmware loading for usb driver to proper kernel method (request_firmware)
|
||||
|
||||
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
|
||||
Cc: Marek Belisko <marek.belisko@gmail.com>
|
3
drivers/staging/ft1000/ft1000-pcmcia/Makefile
Normal file
3
drivers/staging/ft1000/ft1000-pcmcia/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o
|
||||
ft1000_pcmcia-objs := ft1000_hw.o ft1000_dnld.o ft1000_proc.o ft1000_cs.o
|
||||
|
158
drivers/staging/ft1000/ft1000-pcmcia/boot.h
Normal file
158
drivers/staging/ft1000/ft1000-pcmcia/boot.h
Normal file
@ -0,0 +1,158 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// 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
|
||||
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
|
14
drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
Normal file
14
drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
Normal file
@ -0,0 +1,14 @@
|
||||
device "ft1000_cs"
|
||||
class "network" module "ft1000","ft1000_cs"
|
||||
|
||||
card "flarion FT1000"
|
||||
manfid 0x02cc, 0x0100
|
||||
bind "ft1000_cs"
|
||||
|
||||
card "flarion FT1000"
|
||||
manfid 0x02cc, 0x1000
|
||||
bind "ft1000_cs"
|
||||
|
||||
card "flarion FT1000"
|
||||
manfid 0x02cc, 0x1300
|
||||
bind "ft1000_cs"
|
409
drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
Normal file
409
drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
Normal file
@ -0,0 +1,409 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
//
|
||||
// Copyright (C) 2002 Flarion Technologies, All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or (at your option) any
|
||||
// later version. This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details. You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA.
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// File: ft1000.h
|
||||
//
|
||||
// Description: Common structures and defines
|
||||
//
|
||||
// History:
|
||||
// 8/29/02 Whc Ported to Linux.
|
||||
// 7/19/04 Whc Drop packet and cmd msg with pseudo header
|
||||
// checksum
|
||||
// 10/27/04 Whc Added dynamic downloading of test image.
|
||||
// 01/11/04 Whc Added support for Magnemite ASIC
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef _FT1000H_
|
||||
#define _FT1000H_
|
||||
|
||||
|
||||
#define FT1000_DRV_VER 0x01010300
|
||||
|
||||
#define DSPVERSZ 4
|
||||
#define HWSERNUMSZ 16
|
||||
#define SKUSZ 20
|
||||
#define EUISZ 8
|
||||
#define MODESZ 2
|
||||
#define CALVERSZ 2
|
||||
#define CALDATESZ 6
|
||||
|
||||
// Pseudo Header structure
|
||||
typedef struct _PSEUDO_HDR
|
||||
{
|
||||
unsigned short length; // length of msg body
|
||||
unsigned char source; // hardware source id
|
||||
// Host = 0x10
|
||||
// Dsp = 0x20
|
||||
unsigned char destination; // hardware destination id (refer to source)
|
||||
unsigned char portdest; // software destination port id
|
||||
// Host = 0x00
|
||||
// Applicaton Broadcast = 0x10
|
||||
// Network Stack = 0x20
|
||||
// Dsp OAM = 0x80
|
||||
// Dsp Airlink = 0x90
|
||||
// Dsp Loader = 0xa0
|
||||
// Dsp MIP = 0xb0
|
||||
unsigned char portsrc; // software source port id (refer to portdest)
|
||||
unsigned short sh_str_id; // not used
|
||||
unsigned char control; // not used
|
||||
unsigned char rsvd1;
|
||||
unsigned char seq_num; // message sequence number
|
||||
unsigned char rsvd2;
|
||||
unsigned short qos_class; // not used
|
||||
unsigned short checksum; // pseudo header checksum
|
||||
} __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR;
|
||||
|
||||
// Definitions to maintain compatibility between other platforms
|
||||
#define UCHAR u8
|
||||
#define USHORT u16
|
||||
#define ULONG u32
|
||||
#define BOOLEAN u8
|
||||
#define PULONG u32 *
|
||||
#define PUSHORT u16 *
|
||||
#define PUCHAR u8 *
|
||||
#define PCHAR u8 *
|
||||
#define UINT u32
|
||||
|
||||
#define ELECTRABUZZ_ID 0 // ASIC ID for Electrabuzz
|
||||
#define MAGNEMITE_ID 0x1a01 // ASIC ID for Magnemite
|
||||
|
||||
// MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE
|
||||
#define FT1000_REG_DPRAM_ADDR 0x000E // DPADR - Dual Port Ram Indirect Address Register
|
||||
#define FT1000_REG_SUP_CTRL 0x0020 // HCTR - Host Control Register
|
||||
#define FT1000_REG_SUP_STAT 0x0022 // HSTAT - Host Status Register
|
||||
#define FT1000_REG_RESET 0x0024 // HCTR - Host Control Register
|
||||
#define FT1000_REG_SUP_ISR 0x0026 // HISR - Host Interrupt Status Register
|
||||
#define FT1000_REG_SUP_IMASK 0x0028 // HIMASK - Host Interrupt Mask
|
||||
#define FT1000_REG_DOORBELL 0x002a // DBELL - Door Bell Register
|
||||
#define FT1000_REG_ASIC_ID 0x002e // ASICID - ASIC Identification Number
|
||||
// (Electrabuzz=0 Magnemite=0x1A01)
|
||||
|
||||
// MEMORY MAP FOR ELECTRABUZZ ASIC
|
||||
|
||||
#define FT1000_REG_UFIFO_STAT 0x0000 // UFSR - Uplink FIFO status register
|
||||
#define FT1000_REG_UFIFO_BEG 0x0002 // UFBR - Uplink FIFO beginning register
|
||||
#define FT1000_REG_UFIFO_MID 0x0004 // UFMR - Uplink FIFO middle register
|
||||
#define FT1000_REG_UFIFO_END 0x0006 // UFER - Uplink FIFO end register
|
||||
#define FT1000_REG_DFIFO_STAT 0x0008 // DFSR - Downlink FIFO status register
|
||||
#define FT1000_REG_DFIFO 0x000A // DFR - Downlink FIFO Register
|
||||
#define FT1000_REG_DPRAM_DATA 0x000C // DPRAM - Dual Port Indirect Data Register
|
||||
#define FT1000_REG_WATERMARK 0x0010 // WMARK - Watermark Register
|
||||
|
||||
// MEMORY MAP FOR MAGNEMITE
|
||||
#define FT1000_REG_MAG_UFDR 0x0000 // UFDR - Uplink FIFO Data Register (32-bits)
|
||||
#define FT1000_REG_MAG_UFDRL 0x0000 // UFDRL - Uplink FIFO Data Register low-word (16-bits)
|
||||
#define FT1000_REG_MAG_UFDRH 0x0002 // UFDRH - Uplink FIFO Data Register high-word (16-bits)
|
||||
#define FT1000_REG_MAG_UFER 0x0004 // UFER - Uplink FIFO End Register
|
||||
#define FT1000_REG_MAG_UFSR 0x0006 // UFSR - Uplink FIFO Status Register
|
||||
#define FT1000_REG_MAG_DFR 0x0008 // DFR - Downlink FIFO Register (32-bits)
|
||||
#define FT1000_REG_MAG_DFRL 0x0008 // DFRL - Downlink FIFO Register low-word (16-bits)
|
||||
#define FT1000_REG_MAG_DFRH 0x000a // DFRH - Downlink FIFO Register high-word (16-bits)
|
||||
#define FT1000_REG_MAG_DFSR 0x000c // DFSR - Downlink FIFO Status Register
|
||||
#define FT1000_REG_MAG_DPDATA 0x0010 // DPDATA - Dual Port RAM Indirect Data Register (32-bits)
|
||||
#define FT1000_REG_MAG_DPDATAL 0x0010 // DPDATAL - Dual Port RAM Indirect Data Register low-word (16-bits)
|
||||
#define FT1000_REG_MAG_DPDATAH 0x0012 // DPDATAH - Dual Port RAM Indirect Data Register high-word (16-bits)
|
||||
#define FT1000_REG_MAG_WATERMARK 0x002c // WMARK - Watermark Register
|
||||
|
||||
// Reserved Dual Port RAM offsets for Electrabuzz
|
||||
#define FT1000_DPRAM_TX_BASE 0x0002 // Host to PC Card Messaging Area
|
||||
#define FT1000_DPRAM_RX_BASE 0x0800 // PC Card to Host Messaging Area
|
||||
#define FT1000_FIFO_LEN 0x7FC // total length for DSP FIFO tracking
|
||||
#define FT1000_HI_HO 0x7FE // heartbeat with HI/HO
|
||||
#define FT1000_DSP_STATUS 0xFFE // dsp status - non-zero is a request to reset dsp
|
||||
#define FT1000_DSP_LED 0xFFA // dsp led status for PAD device
|
||||
#define FT1000_DSP_CON_STATE 0xFF8 // DSP Connection Status Info
|
||||
#define FT1000_DPRAM_FEFE 0x002 // location for dsp ready indicator
|
||||
#define FT1000_DSP_TIMER0 0x1FF0 // Timer Field from Basestation
|
||||
#define FT1000_DSP_TIMER1 0x1FF2 // Timer Field from Basestation
|
||||
#define FT1000_DSP_TIMER2 0x1FF4 // Timer Field from Basestation
|
||||
#define FT1000_DSP_TIMER3 0x1FF6 // Timer Field from Basestation
|
||||
|
||||
// Reserved Dual Port RAM offsets for Magnemite
|
||||
#define FT1000_DPRAM_MAG_TX_BASE 0x0000 // Host to PC Card Messaging Area
|
||||
#define FT1000_DPRAM_MAG_RX_BASE 0x0200 // PC Card to Host Messaging Area
|
||||
#define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking
|
||||
#define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index
|
||||
#define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO
|
||||
#define FT1000_MAG_HI_HO_INDX 0x0 // high-word index
|
||||
#define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device
|
||||
#define FT1000_MAG_DSP_LED_INDX 0x0 // dsp led status for PAD device
|
||||
|
||||
#define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info
|
||||
#define FT1000_MAG_DSP_CON_STATE_INDX 0x1 // DSP Connection Status Info
|
||||
|
||||
#define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator
|
||||
#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER0 0x3FC // Timer Field from Basestation
|
||||
#define FT1000_MAG_DSP_TIMER0_INDX 0x1
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER1 0x3FC // Timer Field from Basestation
|
||||
#define FT1000_MAG_DSP_TIMER1_INDX 0x0
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER2 0x3FD // Timer Field from Basestation
|
||||
#define FT1000_MAG_DSP_TIMER2_INDX 0x1
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER3 0x3FD // Timer Field from Basestation
|
||||
#define FT1000_MAG_DSP_TIMER3_INDX 0x0
|
||||
|
||||
#define FT1000_MAG_TOTAL_LEN 0x200
|
||||
#define FT1000_MAG_TOTAL_LEN_INDX 0x1
|
||||
|
||||
#define FT1000_MAG_PH_LEN 0x200
|
||||
#define FT1000_MAG_PH_LEN_INDX 0x0
|
||||
|
||||
#define FT1000_MAG_PORT_ID 0x201
|
||||
#define FT1000_MAG_PORT_ID_INDX 0x0
|
||||
|
||||
#define HOST_INTF_LE 0x0 // Host interface little endian mode
|
||||
#define HOST_INTF_BE 0x1 // Host interface big endian mode
|
||||
|
||||
// PC Card to Host Doorbell assignments
|
||||
#define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has
|
||||
// data for host in DPRAM
|
||||
#define FT1000_ASIC_RESET_REQ 0x0004 // DSP requesting host to reset the ASIC
|
||||
#define FT1000_DSP_ASIC_RESET 0x0008 // DSP indicating host that it will reset the ASIC
|
||||
#define FT1000_DB_COND_RESET 0x0010 // DSP request for a card reset.
|
||||
|
||||
// Host to PC Card Doorbell assignments
|
||||
#define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has
|
||||
// data for DSP in DPRAM.
|
||||
#define FT1000_ASIC_RESET_DSP 0x0400 // Responds to FT1000_ASIC_RESET_REQ
|
||||
#define FT1000_DB_HB 0x1000 // Indicates that supervisor
|
||||
// has a heartbeat message for DSP.
|
||||
|
||||
#define FT1000_DPRAM_BASE 0x0000 // Dual Port RAM starting offset
|
||||
|
||||
#define hi 0x6869 // PC Card heartbeat values
|
||||
#define ho 0x686f // PC Card heartbeat values
|
||||
|
||||
// Magnemite specific defines
|
||||
#define hi_mag 0x6968 // Byte swap hi to avoid additional system call
|
||||
#define ho_mag 0x6f68 // Byte swap ho to avoid additional system call
|
||||
|
||||
//
|
||||
// Bit field definitions for Host Interrupt Status Register
|
||||
//
|
||||
// Indicate the cause of an interrupt.
|
||||
//
|
||||
#define ISR_EMPTY 0x00 // no bits set
|
||||
#define ISR_DOORBELL_ACK 0x01 // Doorbell acknowledge from DSP
|
||||
#define ISR_DOORBELL_PEND 0x02 // Doorbell pending from DSP
|
||||
#define ISR_RCV 0x04 // Packet available in Downlink FIFO
|
||||
#define ISR_WATERMARK 0x08 // Watermark requirements satisfied
|
||||
|
||||
// Bit field definition for Host Interrupt Mask
|
||||
#define ISR_MASK_NONE 0x0000 // no bits set
|
||||
#define ISR_MASK_DOORBELL_ACK 0x0001 // Doorbell acknowledge mask
|
||||
#define ISR_MASK_DOORBELL_PEND 0x0002 // Doorbell pending mask
|
||||
#define ISR_MASK_RCV 0x0004 // Downlink Packet available mask
|
||||
#define ISR_MASK_WATERMARK 0x0008 // Watermark interrupt mask
|
||||
#define ISR_MASK_ALL 0xffff // Mask all interrupts
|
||||
|
||||
// Bit field definition for Host Control Register
|
||||
#define DSP_RESET_BIT 0x0001 // Bit field to control dsp reset state
|
||||
// (0 = out of reset 1 = reset)
|
||||
#define ASIC_RESET_BIT 0x0002 // Bit field to control ASIC reset state
|
||||
// (0 = out of reset 1 = reset)
|
||||
|
||||
// Default interrupt mask (Enable Doorbell pending and Packet available interrupts)
|
||||
#define ISR_DEFAULT_MASK 0x7ff9
|
||||
|
||||
// Application specific IDs
|
||||
#define DSPID 0x20
|
||||
#define HOSTID 0x10
|
||||
#define DSPAIRID 0x90
|
||||
#define DRIVERID 0x00
|
||||
#define NETWORKID 0x20
|
||||
|
||||
// Size of DPRAM Message
|
||||
#define MAX_CMD_SQSIZE 1780
|
||||
|
||||
#define ENET_MAX_SIZE 1514
|
||||
#define ENET_HEADER_SIZE 14
|
||||
|
||||
#define SLOWQ_TYPE 0
|
||||
#define FASTQ_TYPE 1
|
||||
|
||||
#define MAX_DSP_SESS_REC 1024
|
||||
|
||||
#define DSP_QID_OFFSET 4
|
||||
#define PSEUDOSZ 16
|
||||
#define PSEUDOSZWRD 8
|
||||
|
||||
// Maximum number of occurrence of pseudo header errors before resetting PC Card.
|
||||
#define MAX_PH_ERR 300
|
||||
|
||||
// Driver message types
|
||||
#define MEDIA_STATE 0x0010
|
||||
#define TIME_UPDATE 0x0020
|
||||
#define DSP_PROVISION 0x0030
|
||||
#define DSP_INIT_MSG 0x0050
|
||||
#define DSP_HIBERNATE 0x0060
|
||||
|
||||
#define DSP_STORE_INFO 0x0070
|
||||
#define DSP_GET_INFO 0x0071
|
||||
#define GET_DRV_ERR_RPT_MSG 0x0073
|
||||
#define RSP_DRV_ERR_RPT_MSG 0x0074
|
||||
|
||||
// Driver Error Messages for DSP
|
||||
#define DSP_HB_INFO 0x7ef0
|
||||
#define DSP_FIFO_INFO 0x7ef1
|
||||
#define DSP_CONDRESET_INFO 0x7ef2
|
||||
#define DSP_CMDLEN_INFO 0x7ef3
|
||||
#define DSP_CMDPHCKSUM_INFO 0x7ef4
|
||||
#define DSP_PKTPHCKSUM_INFO 0x7ef5
|
||||
#define DSP_PKTLEN_INFO 0x7ef6
|
||||
#define DSP_USER_RESET 0x7ef7
|
||||
#define FIFO_FLUSH_MAXLIMIT 0x7ef8
|
||||
#define FIFO_FLUSH_BADCNT 0x7ef9
|
||||
#define FIFO_ZERO_LEN 0x7efa
|
||||
|
||||
#define HOST_QID_OFFSET 5
|
||||
#define QTYPE_OFFSET 13
|
||||
|
||||
#define SUCCESS 0x00
|
||||
#define FAILURE 0x01
|
||||
#define TRUE 0x1
|
||||
#define FALSE 0x0
|
||||
|
||||
#define MAX_NUM_APP 6
|
||||
|
||||
#define MAXIMUM_ASIC_HB_CNT 15
|
||||
|
||||
typedef struct _DRVMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u8 data[0];
|
||||
} __attribute__ ((packed)) DRVMSG, *PDRVMSG;
|
||||
|
||||
typedef struct _MEDIAMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u16 state;
|
||||
u32 ip_addr;
|
||||
u32 net_mask;
|
||||
u32 gateway;
|
||||
u32 dns_1;
|
||||
u32 dns_2;
|
||||
} __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG;
|
||||
|
||||
typedef struct _TIMEMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u8 timeval[8];
|
||||
} __attribute__ ((packed)) TIMEMSG, *PTIMEMSG;
|
||||
|
||||
typedef struct _DSPINITMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u8 DspVer[DSPVERSZ]; // DSP version number
|
||||
u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
|
||||
u8 Sku[SKUSZ]; // SKU
|
||||
u8 eui64[EUISZ]; // EUI64
|
||||
u8 ProductMode[MODESZ]; // Product Mode (Market/Production)
|
||||
u8 RfCalVer[CALVERSZ]; // Rf Calibration version
|
||||
u8 RfCalDate[CALDATESZ]; // Rf Calibration date
|
||||
} __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG;
|
||||
|
||||
typedef struct _DSPHIBERNATE {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u32 timeout;
|
||||
u16 sess_info[0];
|
||||
} DSPHIBERNATE, *PDSPHIBERNATE;
|
||||
|
||||
typedef struct _APP_INFO_BLOCK
|
||||
{
|
||||
u32 fileobject; // Application's file object
|
||||
u16 app_id; // Application id
|
||||
} APP_INFO_BLOCK, *PAPP_INFO_BLOCK;
|
||||
|
||||
typedef struct _PROV_RECORD {
|
||||
struct list_head list;
|
||||
u8 *pprov_data;
|
||||
} PROV_RECORD, *PPROV_RECORD;
|
||||
|
||||
typedef struct _FT1000_INFO {
|
||||
struct net_device_stats stats;
|
||||
u16 DrvErrNum;
|
||||
u16 AsicID;
|
||||
int ASICResetNum;
|
||||
int DspAsicReset;
|
||||
int PktIntfErr;
|
||||
int DSPResetNum;
|
||||
int NumIOCTLBufs;
|
||||
int IOCTLBufLvl;
|
||||
int DeviceCreated;
|
||||
int CardReady;
|
||||
int DspHibernateFlag;
|
||||
int DSPReady;
|
||||
u8 DeviceName[15];
|
||||
int DeviceMajor;
|
||||
int registered;
|
||||
int mediastate;
|
||||
u16 packetseqnum;
|
||||
u8 squeseqnum; // sequence number on slow queue
|
||||
spinlock_t dpram_lock;
|
||||
u16 CurrentInterruptEnableMask;
|
||||
int InterruptsEnabled;
|
||||
u16 fifo_cnt;
|
||||
u8 DspVer[DSPVERSZ]; // DSP version number
|
||||
u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
|
||||
u8 Sku[SKUSZ]; // SKU
|
||||
u8 eui64[EUISZ]; // EUI64
|
||||
time_t ConTm; // Connection Time
|
||||
u16 LedStat;
|
||||
u16 ConStat;
|
||||
u16 ProgConStat;
|
||||
u8 ProductMode[MODESZ];
|
||||
u8 RfCalVer[CALVERSZ];
|
||||
u8 RfCalDate[CALDATESZ];
|
||||
u16 DSP_TIME[4];
|
||||
struct list_head prov_list;
|
||||
int appcnt;
|
||||
APP_INFO_BLOCK app_info[MAX_NUM_APP];
|
||||
u16 DSPInfoBlklen;
|
||||
u16 DrvMsgPend;
|
||||
int (*ft1000_reset)(void *);
|
||||
void *link;
|
||||
u16 DSPInfoBlk[MAX_DSP_SESS_REC];
|
||||
union {
|
||||
u16 Rec[MAX_DSP_SESS_REC];
|
||||
u32 MagRec[MAX_DSP_SESS_REC/2];
|
||||
} DSPSess;
|
||||
struct proc_dir_entry *proc_ft1000;
|
||||
char netdevname[IFNAMSIZ];
|
||||
} FT1000_INFO, *PFT1000_INFO;
|
||||
|
||||
typedef struct _DPRAM_BLK {
|
||||
struct list_head list;
|
||||
u16 *pbuffer;
|
||||
} __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK;
|
||||
|
||||
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);
|
||||
|
||||
#endif // _FT1000H_
|
BIN
drivers/staging/ft1000/ft1000-pcmcia/ft1000.img
Executable file
BIN
drivers/staging/ft1000/ft1000-pcmcia/ft1000.img
Executable file
Binary file not shown.
513
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
Normal file
513
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
Normal file
@ -0,0 +1,513 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
|
||||
Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
||||
Copyright (C) 2002 Flarion Technologies, All rights reserved.
|
||||
Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
|
||||
Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
|
||||
|
||||
The initial developer of the original code is David A. Hinds
|
||||
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds.
|
||||
|
||||
This file was modified to support the Flarion Flash OFDM NIC Device
|
||||
by Wai Chan (w.chan@flarion.com).
|
||||
|
||||
Port for kernel 2.6 created by Patrik Ostrihon (patrik.ostrihon@pwc.sk)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option) any
|
||||
later version. This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place -
|
||||
Suite 330, Boston, MA 02111-1307, USA.
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
//#include <pcmcia/version.h> // Slavius 21.10.2009 removed from kernel
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "ft1000_cs.h" // Slavius 21.10.2009 because CS_SUCCESS constant is missing due to removed pcmcia/version.h
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Module parameters */
|
||||
|
||||
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
|
||||
|
||||
MODULE_AUTHOR("Wai Chan");
|
||||
MODULE_DESCRIPTION("FT1000 PCMCIA driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Newer, simpler way of listing specific interrupts */
|
||||
|
||||
/* The old way: bit map of interrupts to choose from */
|
||||
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
|
||||
|
||||
/*
|
||||
All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
|
||||
you do not define PCMCIA_DEBUG at all, all the debug code will be
|
||||
left out. If you compile with PCMCIA_DEBUG=0, the debug code will
|
||||
be present but disabled.
|
||||
*/
|
||||
#ifdef FT_DEBUG
|
||||
#define DEBUG(n, args...) printk(KERN_DEBUG args)
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
struct net_device *init_ft1000_card(int, int, unsigned char *,
|
||||
void *ft1000_reset, struct pcmcia_device * link,
|
||||
struct device *fdev);
|
||||
void stop_ft1000_card(struct net_device *);
|
||||
|
||||
static int ft1000_config(struct pcmcia_device *link);
|
||||
static void ft1000_release(struct pcmcia_device *link);
|
||||
|
||||
/*
|
||||
The attach() and detach() entry points are used to create and destroy
|
||||
"instances" of the driver, where each instance represents everything
|
||||
needed to manage one actual PCMCIA card.
|
||||
*/
|
||||
|
||||
static void ft1000_detach(struct pcmcia_device *link);
|
||||
static int ft1000_attach(struct pcmcia_device *link);
|
||||
|
||||
typedef struct local_info_t {
|
||||
struct pcmcia_device *link;
|
||||
struct net_device *dev;
|
||||
} local_info_t;
|
||||
|
||||
#define MAX_ASIC_RESET_CNT 10
|
||||
#define COR_DEFAULT 0x55
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void ft1000_reset(struct pcmcia_device * link)
|
||||
{
|
||||
conf_reg_t reg;
|
||||
|
||||
DEBUG(0, "ft1000_cs:ft1000_reset is called................\n");
|
||||
|
||||
/* Soft-Reset card */
|
||||
reg.Action = CS_WRITE;
|
||||
reg.Offset = CISREG_COR;
|
||||
reg.Value = COR_SOFT_RESET;
|
||||
pcmcia_access_configuration_register(link, ®);
|
||||
|
||||
/* Wait until the card has acknowledged our reset */
|
||||
udelay(2);
|
||||
|
||||
/* Restore original COR configuration index */
|
||||
/* Need at least 2 write to respond */
|
||||
reg.Action = CS_WRITE;
|
||||
reg.Offset = CISREG_COR;
|
||||
reg.Value = COR_DEFAULT;
|
||||
pcmcia_access_configuration_register(link, ®);
|
||||
|
||||
/* Wait until the card has finished restarting */
|
||||
udelay(1);
|
||||
|
||||
reg.Action = CS_WRITE;
|
||||
reg.Offset = CISREG_COR;
|
||||
reg.Value = COR_DEFAULT;
|
||||
pcmcia_access_configuration_register(link, ®);
|
||||
|
||||
/* Wait until the card has finished restarting */
|
||||
udelay(1);
|
||||
|
||||
reg.Action = CS_WRITE;
|
||||
reg.Offset = CISREG_COR;
|
||||
reg.Value = COR_DEFAULT;
|
||||
pcmcia_access_configuration_register(link, ®);
|
||||
|
||||
/* Wait until the card has finished restarting */
|
||||
udelay(1);
|
||||
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int get_tuple_first(struct pcmcia_device *link, tuple_t * tuple,
|
||||
cisparse_t * parse)
|
||||
{
|
||||
int i;
|
||||
i = pcmcia_get_first_tuple(link, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
i = pcmcia_get_tuple_data(link, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter
|
||||
}
|
||||
|
||||
static int get_tuple_next(struct pcmcia_device *link, tuple_t * tuple,
|
||||
cisparse_t * parse)
|
||||
{
|
||||
int i;
|
||||
i = pcmcia_get_next_tuple(link, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
i = pcmcia_get_tuple_data(link, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int ft1000_attach(struct pcmcia_device *link)
|
||||
{
|
||||
|
||||
local_info_t *local;
|
||||
|
||||
DEBUG(0, "ft1000_cs: ft1000_attach()\n");
|
||||
|
||||
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
|
||||
if (!local) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(local, 0, sizeof(local_info_t));
|
||||
local->link = link;
|
||||
|
||||
link->priv = local;
|
||||
local->dev = NULL;
|
||||
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->irq.Handler = NULL;
|
||||
|
||||
return ft1000_config(link);
|
||||
} /* ft1000_attach */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
This deletes a driver "instance". The device is de-registered
|
||||
with Card Services. If it has been released, all local data
|
||||
structures are freed. Otherwise, the structures will be freed
|
||||
when the device is released.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void ft1000_detach(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = ((local_info_t *) link->priv)->dev;
|
||||
|
||||
DEBUG(0, "ft1000_cs: ft1000_detach(0x%p)\n", link);
|
||||
|
||||
if (link == NULL) {
|
||||
DEBUG(0,"ft1000_cs:ft1000_detach: Got a NULL pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
stop_ft1000_card(dev);
|
||||
}
|
||||
|
||||
ft1000_release(link);
|
||||
|
||||
/* This points to the parent local_info_t struct */
|
||||
free_netdev(dev);
|
||||
|
||||
} /* ft1000_detach */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
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.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#define CS_CHECK(fn, ret) \
|
||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||
|
||||
#define CFG_CHECK(fn, ret) \
|
||||
last_fn = (fn); if ((last_ret = (ret)) != 0) goto next_entry
|
||||
|
||||
static int ft1000_config(struct pcmcia_device * link)
|
||||
{
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
int last_fn, last_ret, i;
|
||||
u_char buf[64];
|
||||
cistpl_lan_node_id_t *node_id;
|
||||
cistpl_cftable_entry_t dflt = { 0 };
|
||||
cistpl_cftable_entry_t *cfg;
|
||||
unsigned char mac_address[6];
|
||||
|
||||
DEBUG(0, "ft1000_cs: ft1000_config(0x%p)\n", link);
|
||||
|
||||
/*
|
||||
This reads the card's CONFIG tuple to find its configuration
|
||||
registers.
|
||||
*/
|
||||
// tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
// tuple.Attributes = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.TupleOffset = 0;
|
||||
// CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
// CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
|
||||
// CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
|
||||
// link->conf.ConfigBase = parse.config.base;
|
||||
// link->conf.Present = parse.config.rmask[0];
|
||||
|
||||
/*
|
||||
In this loop, we scan the CIS for configuration table entries,
|
||||
each of which describes a valid card configuration, including
|
||||
voltage, IO window, memory window, and interrupt settings.
|
||||
|
||||
We make no assumptions about the card to be configured: we use
|
||||
just the information available in the CIS. In an ideal world,
|
||||
this would work for any PCMCIA card, but it requires a complete
|
||||
and accurate CIS. In practice, a driver usually "knows" most of
|
||||
these things without consulting the CIS, and most client drivers
|
||||
will only use the CIS to fill in implementation-defined details.
|
||||
*/
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
tuple.Attributes = 0;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
while (1) {
|
||||
cfg = &(parse.cftable_entry);
|
||||
CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
|
||||
CFG_CHECK(ParseTuple,
|
||||
pcmcia_parse_tuple(&tuple, &parse)); // Slavius 21.10.2009 removed unused link parameter
|
||||
|
||||
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
|
||||
dflt = *cfg;
|
||||
if (cfg->index == 0)
|
||||
goto next_entry;
|
||||
link->conf.ConfigIndex = cfg->index;
|
||||
|
||||
/* Do we need to allocate an interrupt? */
|
||||
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
|
||||
link->conf.Attributes |= CONF_ENABLE_IRQ;
|
||||
|
||||
/* IO window settings */
|
||||
link->io.NumPorts1 = link->io.NumPorts2 = 0;
|
||||
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
|
||||
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
if (!(io->flags & CISTPL_IO_8BIT)) {
|
||||
DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_16\n");
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
|
||||
}
|
||||
if (!(io->flags & CISTPL_IO_16BIT)) {
|
||||
DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_8\n");
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
}
|
||||
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
|
||||
link->io.BasePort1 = io->win[0].base;
|
||||
link->io.NumPorts1 = io->win[0].len;
|
||||
if (io->nwin > 1) {
|
||||
link->io.Attributes2 = link->io.Attributes1;
|
||||
link->io.BasePort2 = io->win[1].base;
|
||||
link->io.NumPorts2 = io->win[1].len;
|
||||
}
|
||||
/* This reserves IO space but doesn't actually enable it */
|
||||
pcmcia_request_io(link, &link->io);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
next_entry:
|
||||
last_ret = pcmcia_get_next_tuple(link, &tuple);
|
||||
}
|
||||
if (last_ret != CS_SUCCESS) {
|
||||
cs_error(link, RequestIO, last_ret);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate an interrupt line. Note that this does not assign a
|
||||
handler to the interrupt, unless the 'Handler' member of the
|
||||
irq structure is initialized.
|
||||
*/
|
||||
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
|
||||
|
||||
/*
|
||||
This actually configures the PCMCIA socket -- setting up
|
||||
the I/O windows and the interrupt mapping, and putting the
|
||||
card and host interface into "Memory and IO" mode.
|
||||
*/
|
||||
CS_CHECK(RequestConfiguration,
|
||||
pcmcia_request_configuration(link, &link->conf));
|
||||
|
||||
/* Get MAC address from tuples */
|
||||
|
||||
tuple.Attributes = tuple.TupleOffset = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
|
||||
/* Check for a LAN function extension tuple */
|
||||
tuple.DesiredTuple = CISTPL_FUNCE;
|
||||
i = get_tuple_first(link, &tuple, &parse);
|
||||
while (i == CS_SUCCESS) {
|
||||
if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID)
|
||||
break;
|
||||
i = get_tuple_next(link, &tuple, &parse);
|
||||
}
|
||||
|
||||
if (i == CS_SUCCESS) {
|
||||
node_id = (cistpl_lan_node_id_t *) parse.funce.data;
|
||||
if (node_id->nb == 6) {
|
||||
for (i = 0; i < 6; i++)
|
||||
mac_address[i] = node_id->id[i];
|
||||
}
|
||||
}
|
||||
|
||||
((local_info_t *) link->priv)->dev =
|
||||
init_ft1000_card(link->irq.AssignedIRQ, link->io.BasePort1,
|
||||
&mac_address[0], ft1000_reset, link,
|
||||
&handle_to_dev(link));
|
||||
|
||||
/*
|
||||
At this point, the dev_node_t structure(s) need to be
|
||||
initialized and arranged in a linked list at link->dev.
|
||||
*/
|
||||
|
||||
/* Finally, report what we've done */
|
||||
|
||||
return 0;
|
||||
|
||||
cs_failed:
|
||||
cs_error(link, last_fn, last_ret);
|
||||
failed:
|
||||
ft1000_release(link);
|
||||
return -ENODEV;
|
||||
|
||||
} /* ft1000_config */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
After a card is removed, ft1000_release() will unregister the
|
||||
device, and release the PCMCIA configuration. If the device is
|
||||
still open, this will be postponed until it is closed.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void ft1000_release(struct pcmcia_device * link)
|
||||
{
|
||||
|
||||
DEBUG(0, "ft1000_cs: ft1000_release(0x%p)\n", link);
|
||||
|
||||
/*
|
||||
If the device is currently in use, we won't release until it
|
||||
is actually closed, because until then, we can't be sure that
|
||||
no one will try to access the device or its data structures.
|
||||
*/
|
||||
|
||||
/* Unlink the device chain */
|
||||
link->dev_node = NULL;
|
||||
|
||||
/*
|
||||
In a normal driver, additional code may be needed to release
|
||||
other kernel data structures associated with this device.
|
||||
*/
|
||||
|
||||
/* Don't bother checking to see if these succeed or not */
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
} /* ft1000_release */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
The card status event handler. Mostly, this schedules other
|
||||
stuff to run after an event is received.
|
||||
|
||||
When a CARD_REMOVAL event is received, we immediately set a
|
||||
private flag to block future accesses to this device. All the
|
||||
functions that actually access the device should check this flag
|
||||
to make sure the card is still present.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int ft1000_suspend(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = ((local_info_t *) link->priv)->dev;
|
||||
|
||||
DEBUG(1, "ft1000_cs: ft1000_event(0x%06x)\n", event);
|
||||
|
||||
if (link->open)
|
||||
netif_device_detach(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ft1000_resume(struct pcmcia_device *link)
|
||||
{
|
||||
/* struct net_device *dev = link->priv;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static 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,
|
||||
.drv = {
|
||||
.name = "ft1000_cs",
|
||||
},
|
||||
.probe = ft1000_attach,
|
||||
.remove = ft1000_detach,
|
||||
.id_table = ft1000_ids,
|
||||
.suspend = ft1000_suspend,
|
||||
.resume = ft1000_resume,
|
||||
};
|
||||
|
||||
static int __init init_ft1000_cs(void)
|
||||
{
|
||||
DEBUG(0, "ft1000_cs: loading\n");
|
||||
return pcmcia_register_driver(&ft1000_cs_driver);
|
||||
}
|
||||
|
||||
static void __exit exit_ft1000_cs(void)
|
||||
{
|
||||
DEBUG(0, "ft1000_cs: unloading\n");
|
||||
pcmcia_unregister_driver(&ft1000_cs_driver);
|
||||
}
|
||||
|
||||
module_init(init_ft1000_cs);
|
||||
module_exit(exit_ft1000_cs);
|
1
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h
Normal file
1
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h
Normal file
@ -0,0 +1 @@
|
||||
#define CS_SUCCESS 0x00
|
66
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
Normal file
66
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
Normal file
@ -0,0 +1,66 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
//
|
||||
// Copyright (C) 2002 Flarion Technologies, All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or (at your option) any
|
||||
// later version. This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details. You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA.
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// File: ft1000_dev.h
|
||||
//
|
||||
// Description: Register definitions and bit masks for the FT1000 NIC
|
||||
//
|
||||
// History:
|
||||
// 2/5/02 Ivan Bohannon Written.
|
||||
// 8/29/02 Whc Ported to Linux.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef _FT1000_DEVH_
|
||||
#define _FT1000_DEVH_
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Function: ft1000_read_reg
|
||||
// Descripton: This function will read the value of a given ASIC register.
|
||||
// Input:
|
||||
// dev - device structure
|
||||
// offset - ASIC register offset
|
||||
// Output:
|
||||
// data - ASIC register value
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static inline u16 ft1000_read_reg (struct net_device *dev, u16 offset) {
|
||||
u16 data = 0;
|
||||
|
||||
data = inw(dev->base_addr + offset);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Function: ft1000_write_reg
|
||||
// Descripton: This function will set the value for a given ASIC register.
|
||||
// Input:
|
||||
// dev - device structure
|
||||
// offset - ASIC register offset
|
||||
// value - value to write
|
||||
// Output:
|
||||
// None.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static inline void ft1000_write_reg (struct net_device *dev, u16 offset, u16 value) {
|
||||
outw (value, dev->base_addr + offset);
|
||||
}
|
||||
|
||||
#endif // _FT1000_DEVH_
|
||||
|
940
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
Normal file
940
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
Normal file
@ -0,0 +1,940 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
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 __KERNEL_SYSCALLS__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "ft1000_dev.h"
|
||||
#include "ft1000.h"
|
||||
#include "boot.h"
|
||||
|
||||
#ifdef FT_DEBUG
|
||||
#define DEBUG(n, args...) printk(KERN_DEBUG args);
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
USHORT get_handshake(struct net_device *dev, USHORT expected_value);
|
||||
void put_handshake(struct net_device *dev, USHORT handshake_value);
|
||||
USHORT 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);
|
||||
USHORT hdr_checksum(PPSEUDO_HDR pHdr);
|
||||
|
||||
typedef struct _DSP_FILE_HDR {
|
||||
long build_date;
|
||||
long dsp_coff_date;
|
||||
long loader_code_address;
|
||||
long loader_code_size;
|
||||
long loader_code_end;
|
||||
long dsp_code_address;
|
||||
long dsp_code_size;
|
||||
long dsp_code_end;
|
||||
long reserved[8];
|
||||
} __attribute__ ((packed)) DSP_FILE_HDR, *PDSP_FILE_HDR;
|
||||
|
||||
typedef struct _DSP_FILE_HDR_5 {
|
||||
long version_id; // Version ID of this image format.
|
||||
long package_id; // Package ID of code release.
|
||||
long build_date; // Date/time stamp when file was built.
|
||||
long commands_offset; // Offset to attached commands in Pseudo Hdr format.
|
||||
long loader_offset; // Offset to bootloader code.
|
||||
long loader_code_address; // Start address of bootloader.
|
||||
long loader_code_end; // Where bootloader code ends.
|
||||
long loader_code_size;
|
||||
long version_data_offset; // Offset were scrambled version data begins.
|
||||
long version_data_size; // Size, in words, of scrambled version data.
|
||||
long nDspImages; // Number of DSP images in file.
|
||||
} __attribute__ ((packed)) DSP_FILE_HDR_5, *PDSP_FILE_HDR_5;
|
||||
|
||||
typedef struct _DSP_IMAGE_INFO {
|
||||
long coff_date; // Date/time when DSP Coff image was built.
|
||||
long begin_offset; // Offset in file where image begins.
|
||||
long end_offset; // Offset in file where image begins.
|
||||
long run_address; // On chip Start address of DSP code.
|
||||
long image_size; // Size of image.
|
||||
long version; // Embedded version # of DSP code.
|
||||
} __attribute__ ((packed)) DSP_IMAGE_INFO, *PDSP_IMAGE_INFO;
|
||||
|
||||
typedef struct _DSP_IMAGE_INFO_V6 {
|
||||
long coff_date; // Date/time when DSP Coff image was built.
|
||||
long begin_offset; // Offset in file where image begins.
|
||||
long end_offset; // Offset in file where image begins.
|
||||
long run_address; // On chip Start address of DSP code.
|
||||
long image_size; // Size of image.
|
||||
long version; // Embedded version # of DSP code.
|
||||
unsigned short checksum; // Dsp File checksum
|
||||
unsigned short pad1;
|
||||
} __attribute__ ((packed)) DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6;
|
||||
|
||||
void card_bootload(struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
PULONG pdata;
|
||||
UINT size;
|
||||
UINT i;
|
||||
ULONG templong;
|
||||
|
||||
DEBUG(0, "card_bootload is called\n");
|
||||
|
||||
pdata = (PULONG) 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);
|
||||
}
|
||||
|
||||
USHORT get_handshake(struct net_device *dev, USHORT expected_value)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
USHORT handshake;
|
||||
ULONG 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 = (USHORT) tempx;
|
||||
}
|
||||
|
||||
if ((handshake == expected_value)
|
||||
|| (handshake == HANDSHAKE_RESET_VALUE)) {
|
||||
return handshake;
|
||||
} else {
|
||||
loopcnt++;
|
||||
mdelay(DSP_WAIT_SLEEP_TIME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return HANDSHAKE_TIMEOUT_VALUE;
|
||||
|
||||
}
|
||||
|
||||
void put_handshake(struct net_device *dev, USHORT handshake_value)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
ULONG 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 = (ULONG) handshake_value;
|
||||
tempx = ntohl(tempx);
|
||||
ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */
|
||||
}
|
||||
}
|
||||
|
||||
USHORT get_request_type(struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
USHORT request_type;
|
||||
ULONG 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 = (USHORT) tempx;
|
||||
}
|
||||
|
||||
return request_type;
|
||||
|
||||
}
|
||||
|
||||
long get_request_value(struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
long value;
|
||||
USHORT 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)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
USHORT size;
|
||||
ULONG tempx;
|
||||
|
||||
if (info->AsicID == ELECTRABUZZ_ID) {
|
||||
size = (USHORT) (lvalue >> 16);
|
||||
|
||||
ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
|
||||
DWNLD_SIZE_MSW_LOC);
|
||||
|
||||
ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
|
||||
|
||||
size = (USHORT) (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 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
USHORT hdr_checksum(PPSEUDO_HDR pHdr)
|
||||
{
|
||||
USHORT *usPtr = (USHORT *) pHdr;
|
||||
USHORT 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, void *pFileStart, UINT FileLength)
|
||||
{
|
||||
FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
|
||||
int Status = SUCCESS;
|
||||
USHORT DspWordCnt = 0;
|
||||
UINT uiState;
|
||||
USHORT handshake;
|
||||
PPSEUDO_HDR pHdr;
|
||||
USHORT usHdrLength;
|
||||
PDSP_FILE_HDR pFileHdr;
|
||||
long word_length;
|
||||
USHORT request;
|
||||
USHORT temp;
|
||||
PPROV_RECORD pprov_record;
|
||||
PUCHAR pbuffer;
|
||||
PDSP_FILE_HDR_5 pFileHdr5;
|
||||
PDSP_IMAGE_INFO pDspImageInfo = NULL;
|
||||
PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL;
|
||||
long requested_version;
|
||||
BOOLEAN bGoodVersion = 0;
|
||||
PDRVMSG pMailBoxData;
|
||||
USHORT *pUsData = NULL;
|
||||
USHORT *pUsFile = NULL;
|
||||
UCHAR *pUcFile = NULL;
|
||||
UCHAR *pBootEnd = NULL;
|
||||
UCHAR *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;
|
||||
|
||||
//
|
||||
// Get version id of file, at first 4 bytes of file, for newer files.
|
||||
//
|
||||
file_version = *(long *)pFileStart;
|
||||
|
||||
uiState = STATE_START_DWNLD;
|
||||
|
||||
pFileHdr = (PDSP_FILE_HDR) pFileStart;
|
||||
pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart;
|
||||
|
||||
switch (file_version) {
|
||||
case 5:
|
||||
case 6:
|
||||
pUsFile =
|
||||
(USHORT *) ((long)pFileStart + pFileHdr5->loader_offset);
|
||||
pUcFile =
|
||||
(UCHAR *) ((long)pFileStart + pFileHdr5->loader_offset);
|
||||
|
||||
pBootEnd =
|
||||
(UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end);
|
||||
|
||||
loader_code_address = pFileHdr5->loader_code_address;
|
||||
loader_code_size = pFileHdr5->loader_code_size;
|
||||
bGoodVersion = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
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 = (USHORT *) ((long)pBootEnd);
|
||||
pUcFile = (UCHAR *) ((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);
|
||||
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 = *pUsFile;
|
||||
//temp = RtlUshortByteSwap(temp);
|
||||
ft1000_write_reg(dev,
|
||||
FT1000_REG_DPRAM_DATA,
|
||||
*pUsFile);
|
||||
pUsFile++;
|
||||
pUcFile += 2;
|
||||
DspWordCnt++;
|
||||
}
|
||||
} 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 = *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:
|
||||
DEBUG(0,
|
||||
"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 */
|
||||
switch (file_version) {
|
||||
case 5:
|
||||
case 6:
|
||||
pUsFile =
|
||||
(USHORT *) ((long)pFileStart
|
||||
+
|
||||
pFileHdr5->
|
||||
commands_offset);
|
||||
pUcFile =
|
||||
(UCHAR *) ((long)pFileStart
|
||||
+
|
||||
pFileHdr5->
|
||||
commands_offset);
|
||||
break;
|
||||
default:
|
||||
Status = FAILURE;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 = *pUsFile;
|
||||
//temp = RtlUshortByteSwap(temp);
|
||||
ft1000_write_reg(dev,
|
||||
FT1000_REG_DPRAM_DATA,
|
||||
*pUsFile);
|
||||
pUsFile++;
|
||||
pUcFile += 2;
|
||||
DspWordCnt++;
|
||||
}
|
||||
} 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 = *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 =
|
||||
(PDRVMSG) & info->DSPInfoBlk[0];
|
||||
pUsData =
|
||||
(USHORT *) & 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 =
|
||||
(USHORT *) ((long)pFileStart +
|
||||
pFileHdr5->
|
||||
version_data_offset);
|
||||
// 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 */
|
||||
ft1000_write_reg(dev,
|
||||
FT1000_REG_DPRAM_DATA,
|
||||
*pUsFile
|
||||
/*temp */
|
||||
);
|
||||
pUsFile++;
|
||||
}
|
||||
} 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 =
|
||||
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);
|
||||
if (file_version == 5) {
|
||||
pDspImageInfo =
|
||||
(PDSP_IMAGE_INFO) ((long)
|
||||
pFileStart
|
||||
+
|
||||
sizeof
|
||||
(DSP_FILE_HDR_5));
|
||||
for (imageN = 0;
|
||||
imageN <
|
||||
pFileHdr5->nDspImages;
|
||||
imageN++) {
|
||||
if (pDspImageInfo->
|
||||
version ==
|
||||
requested_version) {
|
||||
bGoodVersion =
|
||||
TRUE;
|
||||
pUsFile =
|
||||
(USHORT
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfo->
|
||||
begin_offset);
|
||||
pUcFile =
|
||||
(UCHAR
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfo->
|
||||
begin_offset);
|
||||
pCodeEnd =
|
||||
(UCHAR
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfo->
|
||||
end_offset);
|
||||
run_address =
|
||||
pDspImageInfo->
|
||||
run_address;
|
||||
run_size =
|
||||
pDspImageInfo->
|
||||
image_size;
|
||||
break;
|
||||
}
|
||||
pDspImageInfo++;
|
||||
}
|
||||
} else {
|
||||
pDspImageInfoV6 =
|
||||
(PDSP_IMAGE_INFO_V6) ((long)
|
||||
pFileStart
|
||||
+
|
||||
sizeof
|
||||
(DSP_FILE_HDR_5));
|
||||
for (imageN = 0;
|
||||
imageN <
|
||||
pFileHdr5->nDspImages;
|
||||
imageN++) {
|
||||
temp = (USHORT)
|
||||
(pDspImageInfoV6->
|
||||
version);
|
||||
templong = temp;
|
||||
temp = (USHORT)
|
||||
(pDspImageInfoV6->
|
||||
version >> 16);
|
||||
templong |=
|
||||
(temp << 16);
|
||||
if (templong ==
|
||||
requested_version) {
|
||||
bGoodVersion =
|
||||
TRUE;
|
||||
pUsFile =
|
||||
(USHORT
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfoV6->
|
||||
begin_offset);
|
||||
pUcFile =
|
||||
(UCHAR
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfoV6->
|
||||
begin_offset);
|
||||
pCodeEnd =
|
||||
(UCHAR
|
||||
*) ((long)
|
||||
pFileStart
|
||||
+
|
||||
pDspImageInfoV6->
|
||||
end_offset);
|
||||
run_address =
|
||||
pDspImageInfoV6->
|
||||
run_address;
|
||||
run_size =
|
||||
pDspImageInfoV6->
|
||||
image_size;
|
||||
image_chksum =
|
||||
(ULONG)
|
||||
pDspImageInfoV6->
|
||||
checksum;
|
||||
DEBUG(0,
|
||||
"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 (((UINT) (pUcFile) - (UINT) pFileStart) >=
|
||||
(UINT) FileLength) {
|
||||
uiState = STATE_DONE_FILE;
|
||||
break;
|
||||
}
|
||||
|
||||
pHdr = (PPSEUDO_HDR) pUsFile;
|
||||
|
||||
if (pHdr->portdest == 0x80 /* DspOAM */
|
||||
&& (pHdr->portsrc == 0x00 /* Driver */
|
||||
|| pHdr->portsrc == 0x10 /* FMM */ )) {
|
||||
uiState = STATE_SECTION_PROV;
|
||||
} else {
|
||||
DEBUG(1,
|
||||
"FT1000:download:Download error: Bad Port IDs in Pseudo Record\n");
|
||||
DEBUG(1, "\t Port Source = 0x%2.2x\n",
|
||||
pHdr->portsrc);
|
||||
DEBUG(1, "\t Port Destination = 0x%2.2x\n",
|
||||
pHdr->portdest);
|
||||
Status = FAILURE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STATE_SECTION_PROV:
|
||||
|
||||
pHdr = (PPSEUDO_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(PSEUDO_HDR)),
|
||||
GFP_ATOMIC);
|
||||
if (pbuffer) {
|
||||
memcpy(pbuffer, (void *)pUcFile,
|
||||
(UINT) (usHdrLength +
|
||||
sizeof(PSEUDO_HDR)));
|
||||
// link provisioning data
|
||||
pprov_record =
|
||||
kmalloc(sizeof(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 =
|
||||
(UCHAR *) ((UINT) pUcFile +
|
||||
(UINT) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR));
|
||||
if ((UINT) (pUcFile) -
|
||||
(UINT) (pFileStart) >=
|
||||
(UINT) 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;
|
||||
|
||||
}
|
2286
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
Normal file
2286
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
219
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
Normal file
219
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
|
||||
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.
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "ft1000.h"
|
||||
|
||||
#define FT1000_PROC "ft1000"
|
||||
#define MAX_FILE_LEN 255
|
||||
|
||||
#define PUTM_TO_PAGE(len,page,args...) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, args)
|
||||
|
||||
#define PUTX_TO_PAGE(len,page,message,size,var) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, message); \
|
||||
for(i = 0; i < (size - 1); i++) \
|
||||
{ \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \
|
||||
} \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i])
|
||||
|
||||
#define PUTD_TO_PAGE(len,page,message,size,var) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, message); \
|
||||
for(i = 0; i < (size - 1); i++) \
|
||||
{ \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \
|
||||
} \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
|
||||
|
||||
int ft1000ReadProc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int len;
|
||||
int i;
|
||||
FT1000_INFO *info;
|
||||
char *status[] =
|
||||
{ "Idle (Disconnect)", "Searching", "Active (Connected)",
|
||||
"Waiting for L2", "Sleep", "No Coverage", "", ""
|
||||
};
|
||||
char *signal[] = { "", "*", "**", "***", "****" };
|
||||
int strength;
|
||||
int quality;
|
||||
struct timeval tv;
|
||||
time_t delta;
|
||||
|
||||
dev = (struct net_device *)data;
|
||||
info = (FT1000_INFO *) netdev_priv(dev);
|
||||
|
||||
if (off > 0) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wrap-around */
|
||||
|
||||
if (info->AsicID == ELECTRABUZZ_ID) {
|
||||
if (info->DspHibernateFlag == 0) {
|
||||
if (info->ProgConStat != 0xFF) {
|
||||
info->LedStat =
|
||||
ft1000_read_dpram(dev, FT1000_DSP_LED);
|
||||
info->ConStat =
|
||||
ft1000_read_dpram(dev,
|
||||
FT1000_DSP_CON_STATE);
|
||||
} else {
|
||||
info->ConStat = 0xf;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (info->ProgConStat != 0xFF) {
|
||||
info->LedStat =
|
||||
ntohs(ft1000_read_dpram_mag_16
|
||||
(dev, FT1000_MAG_DSP_LED,
|
||||
FT1000_MAG_DSP_LED_INDX));
|
||||
info->ConStat =
|
||||
ntohs(ft1000_read_dpram_mag_16
|
||||
(dev, FT1000_MAG_DSP_CON_STATE,
|
||||
FT1000_MAG_DSP_CON_STATE_INDX));
|
||||
} else {
|
||||
info->ConStat = 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
i = (info->LedStat) & 0xf;
|
||||
switch (i) {
|
||||
case 0x1:
|
||||
strength = 1;
|
||||
break;
|
||||
case 0x3:
|
||||
strength = 2;
|
||||
break;
|
||||
case 0x7:
|
||||
strength = 3;
|
||||
break;
|
||||
case 0xf:
|
||||
strength = 4;
|
||||
break;
|
||||
default:
|
||||
strength = 0;
|
||||
}
|
||||
|
||||
i = (info->LedStat >> 8) & 0xf;
|
||||
switch (i) {
|
||||
case 0x1:
|
||||
quality = 1;
|
||||
break;
|
||||
case 0x3:
|
||||
quality = 2;
|
||||
break;
|
||||
case 0x7:
|
||||
quality = 3;
|
||||
break;
|
||||
case 0xf:
|
||||
quality = 4;
|
||||
break;
|
||||
default:
|
||||
quality = 0;
|
||||
}
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
delta = (tv.tv_sec - info->ConTm);
|
||||
len = 0;
|
||||
PUTM_TO_PAGE(len, page, "Connection Time: %02ld:%02ld:%02ld\n",
|
||||
((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
|
||||
PUTM_TO_PAGE(len, page, "Connection Time[s]: %ld\n", delta);
|
||||
PUTM_TO_PAGE(len, page, "Asic ID: %s\n",
|
||||
(info->AsicID) ==
|
||||
ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
|
||||
PUTX_TO_PAGE(len, page, "SKU: ", SKUSZ, info->Sku);
|
||||
PUTX_TO_PAGE(len, page, "EUI64: ", EUISZ, info->eui64);
|
||||
PUTD_TO_PAGE(len, page, "DSP version number: ", DSPVERSZ, info->DspVer);
|
||||
PUTX_TO_PAGE(len, page, "Hardware Serial Number: ", HWSERNUMSZ,
|
||||
info->HwSerNum);
|
||||
PUTX_TO_PAGE(len, page, "Caliberation Version: ", CALVERSZ,
|
||||
info->RfCalVer);
|
||||
PUTD_TO_PAGE(len, page, "Caliberation Date: ", CALDATESZ,
|
||||
info->RfCalDate);
|
||||
PUTM_TO_PAGE(len, page, "Media State: %s\n",
|
||||
(info->mediastate) ? "link" : "no link");
|
||||
PUTM_TO_PAGE(len, page, "Connection Status: %s\n",
|
||||
status[((info->ConStat) & 0x7)]);
|
||||
PUTM_TO_PAGE(len, page, "RX packets: %ld\n", info->stats.rx_packets);
|
||||
PUTM_TO_PAGE(len, page, "TX packets: %ld\n", info->stats.tx_packets);
|
||||
PUTM_TO_PAGE(len, page, "RX bytes: %ld\n", info->stats.rx_bytes);
|
||||
PUTM_TO_PAGE(len, page, "TX bytes: %ld\n", info->stats.tx_bytes);
|
||||
PUTM_TO_PAGE(len, page, "Signal Strength: %s\n", signal[strength]);
|
||||
PUTM_TO_PAGE(len, page, "Signal Quality: %s\n", signal[quality]);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
|
||||
void *ptr)
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
FT1000_INFO *info;
|
||||
|
||||
info = (FT1000_INFO *) netdev_priv(dev);
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_CHANGENAME:
|
||||
remove_proc_entry(info->netdevname, info->proc_ft1000);
|
||||
create_proc_read_entry(dev->name, 0644, info->proc_ft1000,
|
||||
ft1000ReadProc, dev);
|
||||
snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block ft1000_netdev_notifier = {
|
||||
.notifier_call = ft1000NotifyProc
|
||||
};
|
||||
|
||||
void ft1000InitProc(struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info;
|
||||
|
||||
info = (FT1000_INFO *) netdev_priv(dev);
|
||||
|
||||
info->proc_ft1000 = proc_mkdir(FT1000_PROC, init_net.proc_net);
|
||||
create_proc_read_entry(dev->name, 0644, info->proc_ft1000,
|
||||
ft1000ReadProc, dev);
|
||||
snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
|
||||
register_netdevice_notifier(&ft1000_netdev_notifier);
|
||||
}
|
||||
|
||||
void ft1000CleanupProc(struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info;
|
||||
|
||||
info = (FT1000_INFO *) netdev_priv(dev);
|
||||
|
||||
remove_proc_entry(dev->name, info->proc_ft1000);
|
||||
remove_proc_entry(FT1000_PROC, init_net.proc_net);
|
||||
unregister_netdevice_notifier(&ft1000_netdev_notifier);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ft1000InitProc);
|
||||
EXPORT_SYMBOL(ft1000CleanupProc);
|
3
drivers/staging/ft1000/ft1000-usb/Makefile
Normal file
3
drivers/staging/ft1000/ft1000-usb/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-$(CONFIG_FT1000_USB) += ft1000.o
|
||||
|
||||
ft1000-objs := ft1000_chdev.o ft1000_download.o ft1000_hw.o ft1000_proc.o ft1000_usb.o
|
934
drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c
Normal file
934
drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c
Normal file
@ -0,0 +1,934 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
//
|
||||
// Copyright (C) 2006 Flarion Technologies, All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or (at your option) any
|
||||
// later version. This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details. You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA.
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// File: ft1000_chdev.c
|
||||
//
|
||||
// Description: Custom character device dispatch routines.
|
||||
//
|
||||
// History:
|
||||
// 8/29/02 Whc Ported to Linux.
|
||||
// 6/05/06 Whc Porting to Linux 2.6.9
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include "ft1000_usb.h"
|
||||
//#include "ft1000_ioctl.h"
|
||||
|
||||
void ft1000_DestroyDevice(struct net_device *dev);
|
||||
u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow);
|
||||
u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx);
|
||||
|
||||
extern inline u16 ft1000_asic_read (struct net_device *dev, u16 offset);
|
||||
extern inline void ft1000_asic_write (struct net_device *dev, u16 offset, u16 value);
|
||||
extern void CardSendCommand(struct ft1000_device *ft1000dev, unsigned short *ptempbuffer, int size);
|
||||
|
||||
static int ft1000_ChOpen (struct inode *Inode, struct file *File);
|
||||
static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait);
|
||||
static int ft1000_ChIoctl (struct inode *Inode, struct file *File, unsigned int Command,
|
||||
unsigned long Argument);
|
||||
static int ft1000_ChRelease (struct inode *Inode, struct file *File);
|
||||
|
||||
static int ft1000_flarion_cnt = 0;
|
||||
|
||||
//need to looking usage of ft1000Handle
|
||||
|
||||
|
||||
|
||||
// Global pointer to device object
|
||||
static struct ft1000_device *pdevobj[MAX_NUM_CARDS + 2];
|
||||
//static devfs_handle_t ft1000Handle[MAX_NUM_CARDS];
|
||||
|
||||
// List to free receive command buffer pool
|
||||
struct list_head freercvpool;
|
||||
|
||||
// lock to arbitrate free buffer list for receive command data
|
||||
spinlock_t free_buff_lock;
|
||||
|
||||
int numofmsgbuf = 0;
|
||||
|
||||
// Global variable to indicate that all provisioning data is sent to DSP
|
||||
//BOOLEAN fProvComplete;
|
||||
|
||||
//
|
||||
// Table of entry-point routines for char device
|
||||
//
|
||||
static struct file_operations ft1000fops =
|
||||
{
|
||||
ioctl: ft1000_ChIoctl,
|
||||
poll: ft1000_ChPoll,
|
||||
open: ft1000_ChOpen,
|
||||
release: ft1000_ChRelease
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: exec_mknod
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int exec_mknod (void *pdata)
|
||||
{
|
||||
PFT1000_INFO info;
|
||||
char mjnum[4];
|
||||
char minornum[4];
|
||||
char temp[32];
|
||||
int retcode;
|
||||
// int i; //aelias [-] reason : unused variable
|
||||
char *envp[] = { "HOME=/", "PATH=/usr/bin:/bin", NULL };
|
||||
char *argv[]={"-m 666",temp,"c",mjnum,minornum,NULL};
|
||||
|
||||
info = pdata;
|
||||
DEBUG("ft1000_chdev:exec_mknod is called with major number = %d\n", info->DeviceMajor);
|
||||
sprintf(temp, "%s%s", "/dev/", info->DeviceName) ;
|
||||
sprintf(mjnum, "%d", info->DeviceMajor);
|
||||
sprintf(minornum, "%d", info->CardNumber);
|
||||
|
||||
//char *argv[]={"mknod","-m 666",temp,"c",mjnum,minornum,NULL};
|
||||
// char *argv[]={"-m 666",temp,"c",mjnum,minornum,NULL};
|
||||
|
||||
//for (i=0; i<7;i++)
|
||||
// DEBUG("argv[%d]=%s\n", i, argv[i]);
|
||||
|
||||
|
||||
retcode = call_usermodehelper ("/bin/mknod", argv, envp, 1);
|
||||
if (retcode) {
|
||||
DEBUG("ft1000_chdev:exec_mknod failed to make the node: retcode = %d\n", retcode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: rm_mknod
|
||||
//
|
||||
// Description: This module removes the FT1000 device file
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int rm_mknod (void *pdata)
|
||||
{
|
||||
|
||||
PFT1000_INFO info;
|
||||
//char *argv[4]={"rm", "-f", "/dev/FT1000", NULL};
|
||||
int retcode;
|
||||
char temp[32];
|
||||
char *argv[]={"rm", "-f", temp, NULL};
|
||||
|
||||
info = (PFT1000_INFO)pdata;
|
||||
DEBUG("ft1000_chdev:rm_mknod is called for device %s\n", info->DeviceName);
|
||||
sprintf(temp, "%s%s", "/dev/", info->DeviceName) ;
|
||||
|
||||
// char *argv[]={"rm", "-f", temp, NULL};
|
||||
|
||||
retcode = call_usermodehelper ("/bin/rm", argv, NULL, 1);
|
||||
if (retcode) {
|
||||
DEBUG("ft1000_chdev:rm_mknod failed to remove the node: retcode = %d\n", retcode);
|
||||
}
|
||||
else
|
||||
DEBUG("ft1000_chdev:rm_mknod done!\n");
|
||||
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_get_buffer
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
PDPRAM_BLK ft1000_get_buffer (struct list_head *bufflist)
|
||||
{
|
||||
unsigned long flags;
|
||||
PDPRAM_BLK ptr;
|
||||
|
||||
spin_lock_irqsave(&free_buff_lock, flags);
|
||||
// Check if buffer is available
|
||||
if ( list_empty(bufflist) ) {
|
||||
DEBUG("ft1000_get_buffer: No more buffer - %d\n", numofmsgbuf);
|
||||
ptr = NULL;
|
||||
}
|
||||
else {
|
||||
numofmsgbuf--;
|
||||
ptr = list_entry(bufflist->next, DPRAM_BLK, list);
|
||||
list_del(&ptr->list);
|
||||
//DEBUG("ft1000_get_buffer: number of free msg buffers = %d\n", numofmsgbuf);
|
||||
}
|
||||
spin_unlock_irqrestore(&free_buff_lock, flags);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_free_buffer
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void ft1000_free_buffer (PDPRAM_BLK pdpram_blk, struct list_head *plist)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&free_buff_lock, flags);
|
||||
// Put memory back to list
|
||||
list_add_tail(&pdpram_blk->list, plist);
|
||||
numofmsgbuf++;
|
||||
//DEBUG("ft1000_free_buffer: number of free msg buffers = %d\n", numofmsgbuf);
|
||||
spin_unlock_irqrestore(&free_buff_lock, flags);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_CreateDevice
|
||||
//
|
||||
// Parameters: dev - pointer to adapter object
|
||||
//
|
||||
// Returns: 0 if successful
|
||||
//
|
||||
// Description: Creates a private char device.
|
||||
//
|
||||
// Notes: Only called by init_module().
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int ft1000_CreateDevice(struct ft1000_device *dev)
|
||||
{
|
||||
PFT1000_INFO info = netdev_priv(dev->net);
|
||||
int result;
|
||||
int i;
|
||||
pid_t pid;
|
||||
|
||||
// make a new device name
|
||||
sprintf(info->DeviceName, "%s%d", "FT100", info->CardNumber);
|
||||
|
||||
// Delete any existing FT1000 node
|
||||
pid = kernel_thread (rm_mknod,(void *)info, 0);
|
||||
msleep(1000);
|
||||
|
||||
DEBUG("ft1000_CreateDevice: number of instance = %d\n", ft1000_flarion_cnt);
|
||||
DEBUG("DeviceCreated = %x\n", info->DeviceCreated);
|
||||
|
||||
//save the device info to global array
|
||||
pdevobj[info->CardNumber] = dev;
|
||||
|
||||
DEBUG("ft1000_CreateDevice: ******SAVED pdevobj[%d]=%x\n", info->CardNumber, (unsigned int)pdevobj[info->CardNumber]); //aelias [+] reason:up
|
||||
|
||||
if (info->DeviceCreated)
|
||||
{
|
||||
DEBUG("ft1000_CreateDevice: \"%s\" already registered\n", info->DeviceName);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
// register the device
|
||||
DEBUG("ft1000_CreateDevice: \"%s\" device registration\n", info->DeviceName);
|
||||
info->DeviceMajor = 0;
|
||||
|
||||
result = register_chrdev(info->DeviceMajor, info->DeviceName, &ft1000fops);
|
||||
if (result < 0)
|
||||
{
|
||||
DEBUG("ft1000_CreateDevice: unable to get major %d\n", info->DeviceMajor);
|
||||
return result;
|
||||
}
|
||||
|
||||
DEBUG("ft1000_CreateDevice: registered char device \"%s\"\n", info->DeviceName);
|
||||
|
||||
// save a dynamic device major number
|
||||
if (info->DeviceMajor == 0)
|
||||
{
|
||||
info->DeviceMajor = result;
|
||||
DEBUG("ft1000_PcdCreateDevice: device major = %d\n", info->DeviceMajor);
|
||||
}
|
||||
|
||||
// Create a thread to call user mode app to mknod
|
||||
pid = kernel_thread (exec_mknod, (void *)info, 0);
|
||||
|
||||
// initialize application information
|
||||
info->appcnt = 0;
|
||||
|
||||
// if (ft1000_flarion_cnt == 0) {
|
||||
//
|
||||
// DEBUG("Initialize free_buff_lock and freercvpool\n");
|
||||
// spin_lock_init(&free_buff_lock);
|
||||
//
|
||||
// // initialize a list of buffers to be use for queuing up receive command data
|
||||
// INIT_LIST_HEAD (&freercvpool);
|
||||
//
|
||||
// // create list of free buffers
|
||||
// for (i=0; i<NUM_OF_FREE_BUFFERS; i++) {
|
||||
// // Get memory for DPRAM_DATA link list
|
||||
// pdpram_blk = kmalloc ( sizeof(DPRAM_BLK), GFP_KERNEL );
|
||||
// // Get a block of memory to store command data
|
||||
// pdpram_blk->pbuffer = kmalloc ( MAX_CMD_SQSIZE, GFP_KERNEL );
|
||||
// // link provisioning data
|
||||
// list_add_tail (&pdpram_blk->list, &freercvpool);
|
||||
// }
|
||||
// numofmsgbuf = NUM_OF_FREE_BUFFERS;
|
||||
// }
|
||||
|
||||
|
||||
// initialize application information
|
||||
info->appcnt = 0;
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
info->app_info[i].nTxMsg = 0;
|
||||
info->app_info[i].nRxMsg = 0;
|
||||
info->app_info[i].nTxMsgReject = 0;
|
||||
info->app_info[i].nRxMsgMiss = 0;
|
||||
info->app_info[i].fileobject = 0;
|
||||
info->app_info[i].app_id = i+1;
|
||||
info->app_info[i].DspBCMsgFlag = 0;
|
||||
info->app_info[i].NumOfMsg = 0;
|
||||
init_waitqueue_head(&info->app_info[i].wait_dpram_msg);
|
||||
INIT_LIST_HEAD (&info->app_info[i].app_sqlist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ft1000Handle[info->CardNumber] = devfs_register(NULL, info->DeviceName, DEVFS_FL_AUTO_DEVNUM, 0, 0,
|
||||
// S_IFCHR | S_IRUGO | S_IWUGO, &ft1000fops, NULL);
|
||||
|
||||
|
||||
info->DeviceCreated = TRUE;
|
||||
ft1000_flarion_cnt++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_DestroyDeviceDEBUG
|
||||
//
|
||||
// Parameters: dev - pointer to adapter object
|
||||
//
|
||||
// Description: Destroys a private char device.
|
||||
//
|
||||
// Notes: Only called by cleanup_module().
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void ft1000_DestroyDevice(struct net_device *dev)
|
||||
{
|
||||
PFT1000_INFO info = netdev_priv(dev);
|
||||
int result = 0;
|
||||
pid_t pid;
|
||||
int i;
|
||||
PDPRAM_BLK pdpram_blk;
|
||||
DPRAM_BLK *ptr;
|
||||
|
||||
DEBUG("ft1000_chdev:ft1000_DestroyDevice called\n");
|
||||
|
||||
|
||||
|
||||
if (info->DeviceCreated)
|
||||
{
|
||||
ft1000_flarion_cnt--;
|
||||
unregister_chrdev(info->DeviceMajor, info->DeviceName);
|
||||
DEBUG("ft1000_DestroyDevice: unregistered device \"%s\", result = %d\n",
|
||||
info->DeviceName, result);
|
||||
|
||||
pid = kernel_thread (rm_mknod, (void *)info, 0);
|
||||
|
||||
// Make sure we free any memory reserve for slow Queue
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
while (list_empty(&info->app_info[i].app_sqlist) == 0) {
|
||||
pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list);
|
||||
list_del(&pdpram_blk->list);
|
||||
ft1000_free_buffer(pdpram_blk, &freercvpool);
|
||||
|
||||
}
|
||||
wake_up_interruptible(&info->app_info[i].wait_dpram_msg);
|
||||
}
|
||||
|
||||
// Remove buffer allocated for receive command data
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
while (list_empty(&freercvpool) == 0) {
|
||||
ptr = list_entry(freercvpool.next, DPRAM_BLK, list);
|
||||
list_del(&ptr->list);
|
||||
kfree(ptr->pbuffer);
|
||||
kfree(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// devfs_unregister(ft1000Handle[info->CardNumber]);
|
||||
|
||||
info->DeviceCreated = FALSE;
|
||||
|
||||
pdevobj[info->CardNumber] = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_ChOpen
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int ft1000_ChOpen (struct inode *Inode, struct file *File)
|
||||
{
|
||||
PFT1000_INFO info;
|
||||
int i,num;
|
||||
|
||||
DEBUG("ft1000_ChOpen called\n");
|
||||
num = (MINOR(Inode->i_rdev) & 0xf);
|
||||
DEBUG("ft1000_ChOpen: minor number=%d\n", num);
|
||||
|
||||
for (i=0; i<5; i++)
|
||||
DEBUG("pdevobj[%d]=%x\n", i, (unsigned int)pdevobj[i]); //aelias [+] reason: down
|
||||
|
||||
if ( pdevobj[num] != NULL )
|
||||
//info = (PFT1000_INFO)(pdevobj[num]->net->priv);
|
||||
info = (FT1000_INFO *) netdev_priv (pdevobj[num]->net);
|
||||
else
|
||||
{
|
||||
DEBUG("ft1000_ChOpen: can not find device object %d\n", num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("f_owner = 0x%8x number of application = %d\n", (u32)(&File->f_owner), info->appcnt );
|
||||
|
||||
// Check if maximum number of application exceeded
|
||||
if (info->appcnt > MAX_NUM_APP) {
|
||||
DEBUG("Maximum number of application exceeded\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
// Search for available application info block
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( (info->app_info[i].fileobject == 0) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail due to lack of application info block
|
||||
if (i == MAX_NUM_APP) {
|
||||
DEBUG("Could not find an application info block\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
info->appcnt++;
|
||||
info->app_info[i].fileobject = (u32)(&File->f_owner);
|
||||
info->app_info[i].nTxMsg = 0;
|
||||
info->app_info[i].nRxMsg = 0;
|
||||
info->app_info[i].nTxMsgReject = 0;
|
||||
info->app_info[i].nRxMsgMiss = 0;
|
||||
|
||||
File->private_data = pdevobj[num]->net;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_ChPoll
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct net_device *dev = file->private_data;
|
||||
PFT1000_INFO info;
|
||||
int i;
|
||||
|
||||
//DEBUG("ft1000_ChPoll called\n");
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
DEBUG("FT1000:ft1000_ChPoll called when ft1000_flarion_cnt is zero\n");
|
||||
return (-EBADF);
|
||||
}
|
||||
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
|
||||
// Search for matching file object
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( info->app_info[i].fileobject == (u32)(&file->f_owner) ) {
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find application info block
|
||||
if (i == MAX_NUM_APP) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n");
|
||||
return ( -EACCES );
|
||||
}
|
||||
|
||||
if (list_empty(&info->app_info[i].app_sqlist) == 0) {
|
||||
DEBUG("FT1000:ft1000_ChPoll:Message detected in slow queue\n");
|
||||
return(POLLIN | POLLRDNORM | POLLPRI);
|
||||
}
|
||||
|
||||
poll_wait (file, &info->app_info[i].wait_dpram_msg, wait);
|
||||
//DEBUG("FT1000:ft1000_ChPoll:Polling for data from DSP\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_ChIoctl
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int ft1000_ChIoctl (struct inode *Inode, struct file *File, unsigned int Command,
|
||||
unsigned long Argument)
|
||||
{
|
||||
struct net_device *dev;
|
||||
PFT1000_INFO info;
|
||||
struct ft1000_device *ft1000dev;
|
||||
int result=0;
|
||||
int cmd;
|
||||
int i;
|
||||
u16 tempword;
|
||||
unsigned long flags;
|
||||
struct timeval tv;
|
||||
IOCTL_GET_VER get_ver_data;
|
||||
IOCTL_GET_DSP_STAT get_stat_data;
|
||||
u8 ConnectionMsg[] = {0x00,0x44,0x10,0x20,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x93,0x64,
|
||||
0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x02,0x37,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x7f,0x00,
|
||||
0x00,0x01,0x00,0x00};
|
||||
|
||||
unsigned short ledStat=0;
|
||||
unsigned short conStat=0;
|
||||
|
||||
//DEBUG("ft1000_ChIoctl called\n");
|
||||
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl called when ft1000_flarion_cnt is zero\n");
|
||||
return (-EBADF);
|
||||
}
|
||||
|
||||
//DEBUG("FT1000:ft1000_ChIoctl:Command = 0x%x Argument = 0x%8x\n", Command, (u32)Argument);
|
||||
|
||||
dev = File->private_data;
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
ft1000dev = info->pFt1000Dev;
|
||||
cmd = _IOC_NR(Command);
|
||||
//DEBUG("FT1000:ft1000_ChIoctl:cmd = 0x%x\n", cmd);
|
||||
|
||||
// process the command
|
||||
switch (cmd) {
|
||||
case IOCTL_REGISTER_CMD:
|
||||
DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_REGISTER called\n");
|
||||
result = get_user(tempword, (unsigned short *)Argument);
|
||||
if (result) {
|
||||
DEBUG("result = %d failed to get_user\n", result);
|
||||
break;
|
||||
}
|
||||
if (tempword == DSPBCMSGID) {
|
||||
// Search for matching file object
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) {
|
||||
info->app_info[i].DspBCMsgFlag = 1;
|
||||
DEBUG("FT1000:ft1000_ChIoctl:Registered for broadcast messages\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_GET_VER_CMD:
|
||||
DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_VER called\n");
|
||||
|
||||
get_ver_data.drv_ver = FT1000_DRV_VER;
|
||||
|
||||
if (copy_to_user((PIOCTL_GET_VER)Argument, &get_ver_data, sizeof(get_ver_data)) ) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
|
||||
result = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG("FT1000:ft1000_ChIoctl:driver version = 0x%x\n",(unsigned int)get_ver_data.drv_ver);
|
||||
|
||||
break;
|
||||
case IOCTL_CONNECT:
|
||||
// Connect Message
|
||||
DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_CONNECT\n");
|
||||
ConnectionMsg[79] = 0xfc;
|
||||
CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
|
||||
|
||||
break;
|
||||
case IOCTL_DISCONNECT:
|
||||
// Disconnect Message
|
||||
DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_DISCONNECT\n");
|
||||
ConnectionMsg[79] = 0xfd;
|
||||
CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
|
||||
break;
|
||||
case IOCTL_GET_DSP_STAT_CMD:
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DSP_STAT called\n");
|
||||
|
||||
memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
|
||||
memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
|
||||
memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
|
||||
memcpy(get_stat_data.eui64, info->eui64, EUISZ);
|
||||
|
||||
if (info->ProgConStat != 0xFF) {
|
||||
ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (PUCHAR)&ledStat, FT1000_MAG_DSP_LED_INDX);
|
||||
get_stat_data.LedStat = ntohs(ledStat);
|
||||
DEBUG("FT1000:ft1000_ChIoctl: LedStat = 0x%x\n", get_stat_data.LedStat);
|
||||
ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (PUCHAR)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
|
||||
get_stat_data.ConStat = ntohs(conStat);
|
||||
DEBUG("FT1000:ft1000_ChIoctl: ConStat = 0x%x\n", get_stat_data.ConStat);
|
||||
}
|
||||
else {
|
||||
get_stat_data.ConStat = 0x0f;
|
||||
}
|
||||
|
||||
|
||||
get_stat_data.nTxPkts = info->stats.tx_packets;
|
||||
get_stat_data.nRxPkts = info->stats.rx_packets;
|
||||
get_stat_data.nTxBytes = info->stats.tx_bytes;
|
||||
get_stat_data.nRxBytes = info->stats.rx_bytes;
|
||||
do_gettimeofday ( &tv );
|
||||
get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
|
||||
DEBUG("Connection Time = %d\n", (int)get_stat_data.ConTm);
|
||||
if (copy_to_user((PIOCTL_GET_DSP_STAT)Argument, &get_stat_data, sizeof(get_stat_data)) ) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
|
||||
result = -EFAULT;
|
||||
break;
|
||||
}
|
||||
DEBUG("ft1000_chioctl: GET_DSP_STAT succeed\n");
|
||||
break;
|
||||
case IOCTL_SET_DPRAM_CMD:
|
||||
{
|
||||
IOCTL_DPRAM_BLK dpram_data;
|
||||
//IOCTL_DPRAM_COMMAND dpram_command;
|
||||
USHORT qtype;
|
||||
USHORT msgsz;
|
||||
PPSEUDO_HDR ppseudo_hdr;
|
||||
PUSHORT pmsg;
|
||||
USHORT total_len;
|
||||
USHORT app_index;
|
||||
u16 status;
|
||||
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_SET_DPRAM called\n");
|
||||
|
||||
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
return (-EBADF);
|
||||
}
|
||||
|
||||
if (info->DrvMsgPend) {
|
||||
return (-ENOTTY);
|
||||
}
|
||||
|
||||
if ( (info->DspAsicReset) || (info->fProvComplete == 0) ) {
|
||||
return (-EACCES);
|
||||
}
|
||||
|
||||
info->fAppMsgPend = 1;
|
||||
|
||||
if (info->CardReady) {
|
||||
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: try to SET_DPRAM \n");
|
||||
|
||||
// Get the length field to see how many bytes to copy
|
||||
result = get_user(msgsz, (unsigned short *)Argument);
|
||||
msgsz = ntohs (msgsz);
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: length of message = %d\n", msgsz);
|
||||
|
||||
if (msgsz > MAX_CMD_SQSIZE) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: bad message length = %d\n", msgsz);
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
//if ( copy_from_user(&(dpram_command.dpram_blk), (PIOCTL_DPRAM_BLK)Argument, msgsz+2) ) {
|
||||
if ( copy_from_user(&dpram_data, (PIOCTL_DPRAM_BLK)Argument, msgsz+2) ) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
|
||||
result = -EFAULT;
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
// whc - for debugging only
|
||||
ptr = (char *)&dpram_data;
|
||||
for (i=0; i<msgsz; i++) {
|
||||
DEBUG(1,"FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++);
|
||||
}
|
||||
#endif
|
||||
// Check if this message came from a registered application
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i==MAX_NUM_APP) {
|
||||
DEBUG("FT1000:No matching application fileobject\n");
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
app_index = i;
|
||||
|
||||
// Check message qtype type which is the lower byte within qos_class
|
||||
//qtype = ntohs(dpram_command.dpram_blk.pseudohdr.qos_class) & 0xff;
|
||||
qtype = ntohs(dpram_data.pseudohdr.qos_class) & 0xff;
|
||||
//DEBUG("FT1000_ft1000_ChIoctl: qtype = %d\n", qtype);
|
||||
if (qtype) {
|
||||
}
|
||||
else {
|
||||
// Put message into Slow Queue
|
||||
// Only put a message into the DPRAM if msg doorbell is available
|
||||
status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
|
||||
//DEBUG("FT1000_ft1000_ChIoctl: READ REGISTER tempword=%x\n", tempword);
|
||||
if (tempword & FT1000_DB_DPRAM_TX) {
|
||||
// Suspend for 2ms and try again due to DSP doorbell busy
|
||||
mdelay(2);
|
||||
status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
|
||||
if (tempword & FT1000_DB_DPRAM_TX) {
|
||||
// Suspend for 1ms and try again due to DSP doorbell busy
|
||||
mdelay(1);
|
||||
status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
|
||||
if (tempword & FT1000_DB_DPRAM_TX) {
|
||||
status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
|
||||
if (tempword & FT1000_DB_DPRAM_TX) {
|
||||
// Suspend for 3ms and try again due to DSP doorbell busy
|
||||
mdelay(3);
|
||||
status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
|
||||
if (tempword & FT1000_DB_DPRAM_TX) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl:Doorbell not available\n");
|
||||
result = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//DEBUG("FT1000_ft1000_ChIoctl: finished reading register\n");
|
||||
|
||||
// Make sure we are within the limits of the slow queue memory limitation
|
||||
if ( (msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ) ) {
|
||||
// Need to put sequence number plus new checksum for message
|
||||
//pmsg = (PUSHORT)&dpram_command.dpram_blk.pseudohdr;
|
||||
pmsg = (PUSHORT)&dpram_data.pseudohdr;
|
||||
ppseudo_hdr = (PPSEUDO_HDR)pmsg;
|
||||
total_len = msgsz+2;
|
||||
if (total_len & 0x1) {
|
||||
total_len++;
|
||||
}
|
||||
|
||||
// Insert slow queue sequence number
|
||||
ppseudo_hdr->seq_num = info->squeseqnum++;
|
||||
ppseudo_hdr->portsrc = info->app_info[app_index].app_id;
|
||||
// Calculate new checksum
|
||||
ppseudo_hdr->checksum = *pmsg++;
|
||||
//DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
|
||||
for (i=1; i<7; i++) {
|
||||
ppseudo_hdr->checksum ^= *pmsg++;
|
||||
//DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
|
||||
}
|
||||
pmsg++;
|
||||
ppseudo_hdr = (PPSEUDO_HDR)pmsg;
|
||||
#if 0
|
||||
ptr = (char *)&dpram_data;
|
||||
DEBUG("FT1000:ft1000_ChIoctl: Command Send\n");
|
||||
for (i=0; i<total_len; i++) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++);
|
||||
}
|
||||
#endif
|
||||
//dpram_command.extra = 0;
|
||||
|
||||
//CardSendCommand(ft1000dev,(unsigned char*)&dpram_command,total_len+2);
|
||||
CardSendCommand(ft1000dev,(unsigned short*)&dpram_data,total_len+2);
|
||||
|
||||
|
||||
info->app_info[app_index].nTxMsg++;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG("FT1000:ft1000_ChIoctl: Card not ready take messages\n");
|
||||
result = -EACCES;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case IOCTL_GET_DPRAM_CMD:
|
||||
{
|
||||
PDPRAM_BLK pdpram_blk;
|
||||
PIOCTL_DPRAM_BLK pioctl_dpram;
|
||||
int msglen;
|
||||
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM called\n");
|
||||
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
return (-EBADF);
|
||||
}
|
||||
|
||||
// Search for matching file object
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) {
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find application info block
|
||||
if (i == MAX_NUM_APP) {
|
||||
DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n");
|
||||
result = -EBADF;
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
pioctl_dpram = (PIOCTL_DPRAM_BLK)Argument;
|
||||
if (list_empty(&info->app_info[i].app_sqlist) == 0) {
|
||||
//DEBUG("FT1000:ft1000_ChIoctl:Message detected in slow queue\n");
|
||||
spin_lock_irqsave(&free_buff_lock, flags);
|
||||
pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list);
|
||||
list_del(&pdpram_blk->list);
|
||||
info->app_info[i].NumOfMsg--;
|
||||
//DEBUG("FT1000:ft1000_ChIoctl:NumOfMsg for app %d = %d\n", i, info->app_info[i].NumOfMsg);
|
||||
spin_unlock_irqrestore(&free_buff_lock, flags);
|
||||
msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
|
||||
pioctl_dpram->total_len = htons(msglen);
|
||||
//DEBUG("FT1000:ft1000_ChIoctl:msg length = %x\n", msglen);
|
||||
if(copy_to_user (&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen))
|
||||
{
|
||||
DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
|
||||
result = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
ft1000_free_buffer(pdpram_blk, &freercvpool);
|
||||
result = msglen;
|
||||
}
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM no message\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG("FT1000:ft1000_ChIoctl:unknown command: 0x%x\n", Command);
|
||||
result = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
info->fAppMsgPend = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_ChRelease
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int ft1000_ChRelease (struct inode *Inode, struct file *File)
|
||||
{
|
||||
PFT1000_INFO info;
|
||||
struct net_device *dev;
|
||||
int i;
|
||||
PDPRAM_BLK pdpram_blk;
|
||||
|
||||
DEBUG("ft1000_ChRelease called\n");
|
||||
|
||||
dev = File->private_data;
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
|
||||
if (ft1000_flarion_cnt == 0) {
|
||||
info->appcnt--;
|
||||
return (-EBADF);
|
||||
}
|
||||
|
||||
// Search for matching file object
|
||||
for (i=0; i<MAX_NUM_APP; i++) {
|
||||
if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) {
|
||||
//DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i==MAX_NUM_APP)
|
||||
return 0;
|
||||
|
||||
while (list_empty(&info->app_info[i].app_sqlist) == 0) {
|
||||
DEBUG("Remove and free memory queue up on slow queue\n");
|
||||
pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list);
|
||||
list_del(&pdpram_blk->list);
|
||||
ft1000_free_buffer(pdpram_blk, &freercvpool);
|
||||
}
|
||||
|
||||
// initialize application information
|
||||
info->appcnt--;
|
||||
DEBUG("ft1000_chdev:%s:appcnt = %d\n", __FUNCTION__, info->appcnt);
|
||||
info->app_info[i].fileobject = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1416
drivers/staging/ft1000/ft1000-usb/ft1000_download.c
Normal file
1416
drivers/staging/ft1000/ft1000-usb/ft1000_download.c
Normal file
File diff suppressed because it is too large
Load Diff
2762
drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
Normal file
2762
drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
10
drivers/staging/ft1000/ft1000-usb/ft1000_hw.h
Normal file
10
drivers/staging/ft1000/ft1000-usb/ft1000_hw.h
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
#ifndef _FT1000_HW_H_
|
||||
#define _FT1000_HW_H_
|
||||
|
||||
#include "ft1000_usb.h"
|
||||
|
||||
extern u16 ft1000_read_register(struct usb_device *dev, PUSHORT Data, u8 nRegIndx);
|
||||
extern u16 ft1000_write_register(struct usb_device *dev, USHORT value, u8 nRegIndx);
|
||||
|
||||
#endif
|
140
drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
Normal file
140
drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
Normal file
@ -0,0 +1,140 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// FT1000 driver for Flarion Flash OFDM NIC Device
|
||||
//
|
||||
// Copyright (C) 2002 Flarion Technologies, All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or (at your option) any
|
||||
// later version. This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details. You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place -
|
||||
// Suite 330, Boston, MA 02111-1307, USA.
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// File: ft1000_ioctl.h
|
||||
//
|
||||
// Description: Common structures and defines relating to IOCTL
|
||||
//
|
||||
// History:
|
||||
// 11/5/02 Whc Created.
|
||||
//
|
||||
//---------------------------------------------------------------------------//---------------------------------------------------------------------------
|
||||
#ifndef _FT1000IOCTLH_
|
||||
#define _FT1000IOCTLH_
|
||||
|
||||
#define DSPVERSZ 4
|
||||
#define HWSERNUMSZ 16
|
||||
#define SKUSZ 20
|
||||
#define EUISZ 8
|
||||
#define CALVERSZ 2
|
||||
#define CALDATESZ 6
|
||||
|
||||
#define MAX_DNLD_BLKSZ 1024
|
||||
|
||||
// Standard Flarion Pseudo header
|
||||
typedef struct _PSEUDO_HDR
|
||||
{
|
||||
unsigned short length; //length of msg body
|
||||
unsigned char source; //source address (0x10=Host 0x20=DSP)
|
||||
unsigned char destination; //destination address (refer to source address)
|
||||
unsigned char portdest; //destination port id
|
||||
// 0x00=Driver
|
||||
// 0x10=Application Broadcast
|
||||
// 0x20=Network Stack
|
||||
// 0x80=Dsp OAM
|
||||
// 0x90=Dsp Airlink
|
||||
// 0xa0=Dsp Loader
|
||||
// 0xb0=Dsp MIP
|
||||
unsigned char portsrc; //source port id (refer to portdest)
|
||||
unsigned short sh_str_id; //stream id (Not applicable on Mobile)
|
||||
unsigned char control; //stream id (Not applicable on Mobile)
|
||||
unsigned char rsvd1; //reserved
|
||||
unsigned char seq_num; //sequence number
|
||||
unsigned char rsvd2; //reserved
|
||||
unsigned short qos_class; //Quality of Service class (Not applicable on Mobile)
|
||||
unsigned short checksum; //Psuedo header checksum
|
||||
} __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR;
|
||||
|
||||
typedef struct _IOCTL_GET_VER
|
||||
{
|
||||
unsigned long drv_ver;
|
||||
} __attribute__ ((packed)) IOCTL_GET_VER, *PIOCTL_GET_VER;
|
||||
|
||||
//Data structure for Dsp statistics
|
||||
typedef struct _IOCTL_GET_DSP_STAT
|
||||
{
|
||||
unsigned char DspVer[DSPVERSZ]; // DSP version number
|
||||
unsigned char HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
|
||||
unsigned char Sku[SKUSZ]; // SKU
|
||||
unsigned char eui64[EUISZ]; // EUI64
|
||||
unsigned short ConStat; // Connection Status
|
||||
// Bits 0-3 = Connection Status Field
|
||||
// 0000=Idle (Disconnect)
|
||||
// 0001=Searching
|
||||
// 0010=Active (Connected)
|
||||
// 0011=Waiting for L2 down
|
||||
// 0100=Sleep
|
||||
unsigned short LedStat; // Led Status
|
||||
// Bits 0-3 = Signal Strength Field
|
||||
// 0000 = -105dBm to -92dBm
|
||||
// 0001 = -92dBm to -85dBm
|
||||
// 0011 = -85dBm to -75dBm
|
||||
// 0111 = -75dBm to -50dBm
|
||||
// 1111 = -50dBm to 0dBm
|
||||
// Bits 4-7 = Reserved
|
||||
// Bits 8-11 = SNR Field
|
||||
// 0000 = <2dB
|
||||
// 0001 = 2dB to 8dB
|
||||
// 0011 = 8dB to 15dB
|
||||
// 0111 = 15dB to 22dB
|
||||
// 1111 = >22dB
|
||||
// Bits 12-15 = Reserved
|
||||
unsigned long nTxPkts; // Number of packets transmitted from host to dsp
|
||||
unsigned long nRxPkts; // Number of packets received from dsp to host
|
||||
unsigned long nTxBytes; // Number of bytes transmitted from host to dsp
|
||||
unsigned long nRxBytes; // Number of bytes received from dsp to host
|
||||
unsigned long ConTm; // Current session connection time in seconds
|
||||
unsigned char CalVer[CALVERSZ]; // Proprietary Calibration Version
|
||||
unsigned char CalDate[CALDATESZ]; // Proprietary Calibration Date
|
||||
} __attribute__ ((packed)) IOCTL_GET_DSP_STAT, *PIOCTL_GET_DSP_STAT;
|
||||
|
||||
//Data structure for Dual Ported RAM messaging between Host and Dsp
|
||||
typedef struct _IOCTL_DPRAM_BLK
|
||||
{
|
||||
unsigned short total_len;
|
||||
PSEUDO_HDR pseudohdr;
|
||||
unsigned char buffer[1780];
|
||||
} __attribute__ ((packed)) IOCTL_DPRAM_BLK, *PIOCTL_DPRAM_BLK;
|
||||
|
||||
typedef struct _IOCTL_DPRAM_COMMAND
|
||||
{
|
||||
unsigned short extra;
|
||||
IOCTL_DPRAM_BLK dpram_blk;
|
||||
} __attribute__ ((packed)) IOCTL_DPRAM_COMMAND, *PIOCTL_DPRAM_COMMAND;
|
||||
|
||||
//
|
||||
// Custom IOCTL command codes
|
||||
//
|
||||
#define FT1000_MAGIC_CODE 'F'
|
||||
|
||||
#define IOCTL_REGISTER_CMD 0
|
||||
#define IOCTL_SET_DPRAM_CMD 3
|
||||
#define IOCTL_GET_DPRAM_CMD 4
|
||||
#define IOCTL_GET_DSP_STAT_CMD 6
|
||||
#define IOCTL_GET_VER_CMD 7
|
||||
#define IOCTL_CONNECT 10
|
||||
#define IOCTL_DISCONNECT 11
|
||||
|
||||
#define IOCTL_FT1000_GET_DSP_STAT _IOR (FT1000_MAGIC_CODE, IOCTL_GET_DSP_STAT_CMD, sizeof(IOCTL_GET_DSP_STAT) )
|
||||
#define IOCTL_FT1000_GET_VER _IOR (FT1000_MAGIC_CODE, IOCTL_GET_VER_CMD, sizeof(IOCTL_GET_VER) )
|
||||
#define IOCTL_FT1000_CONNECT _IOW (FT1000_MAGIC_CODE, IOCTL_CONNECT, 0 )
|
||||
#define IOCTL_FT1000_DISCONNECT _IOW (FT1000_MAGIC_CODE, IOCTL_DISCONNECT, 0 )
|
||||
#define IOCTL_FT1000_SET_DPRAM _IOW (FT1000_MAGIC_CODE, IOCTL_SET_DPRAM_CMD, sizeof(IOCTL_DPRAM_BLK) )
|
||||
#define IOCTL_FT1000_GET_DPRAM _IOR (FT1000_MAGIC_CODE, IOCTL_GET_DPRAM_CMD, sizeof(IOCTL_DPRAM_BLK) )
|
||||
#define IOCTL_FT1000_REGISTER _IOW (FT1000_MAGIC_CODE, IOCTL_REGISTER_CMD, sizeof(unsigned short *) )
|
||||
#endif // _FT1000IOCTLH_
|
||||
|
232
drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
Normal file
232
drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
|
||||
#include "ft1000_usb.h"
|
||||
|
||||
#define FT1000_PROC_DIR "ft1000"
|
||||
|
||||
|
||||
#define PUTM_TO_PAGE(len,page,args...) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, args)
|
||||
|
||||
#define PUTX_TO_PAGE(len,page,message,size,var) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, message); \
|
||||
for(i = 0; i < (size - 1); i++) \
|
||||
{ \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \
|
||||
} \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i])
|
||||
|
||||
#define PUTD_TO_PAGE(len,page,message,size,var) \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, message); \
|
||||
for(i = 0; i < (size - 1); i++) \
|
||||
{ \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \
|
||||
} \
|
||||
len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef INIT_NET_NS
|
||||
#define FTNET_PROC init_net.proc_net
|
||||
#else
|
||||
#define FTNET_PROC proc_net
|
||||
#endif
|
||||
|
||||
|
||||
u16 ft1000_read_dpram16 (struct ft1000_device *ft1000dev, USHORT indx,
|
||||
PUCHAR buffer, u8 highlow);
|
||||
|
||||
|
||||
int
|
||||
ft1000ReadProc (char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int len;
|
||||
int i;
|
||||
unsigned short ledStat;
|
||||
unsigned short conStat;
|
||||
|
||||
FT1000_INFO *info;
|
||||
|
||||
char *status[] = { "Idle (Disconnect)", "Searching", "Active (Connected)",
|
||||
"Waiting for L2", "Sleep", "No Coverage", "", ""
|
||||
};
|
||||
|
||||
char *signal[] = { "", "*", "**", "***", "****" };
|
||||
int strength;
|
||||
int quality;
|
||||
struct timeval tv;
|
||||
time_t delta;
|
||||
|
||||
dev = (struct net_device *) data;
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
|
||||
if (off > 0)
|
||||
{
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (info->ProgConStat != 0xFF)
|
||||
{
|
||||
ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_LED,
|
||||
(PUCHAR) & ledStat, FT1000_MAG_DSP_LED_INDX);
|
||||
info->LedStat = ntohs (ledStat);
|
||||
|
||||
ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_CON_STATE,
|
||||
(PUCHAR) & conStat, FT1000_MAG_DSP_CON_STATE_INDX);
|
||||
info->ConStat = ntohs (conStat);
|
||||
do_gettimeofday (&tv);
|
||||
delta = (tv.tv_sec - info->ConTm);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->ConStat = 0xf;
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
i = (info->LedStat) & 0xf;
|
||||
switch (i)
|
||||
{
|
||||
case 0x1:
|
||||
strength = 1;
|
||||
break;
|
||||
case 0x3:
|
||||
strength = 2;
|
||||
break;
|
||||
case 0x7:
|
||||
strength = 3;
|
||||
break;
|
||||
case 0xf:
|
||||
strength = 4;
|
||||
break;
|
||||
default:
|
||||
strength = 0;
|
||||
}
|
||||
|
||||
i = (info->LedStat >> 8) & 0xf;
|
||||
switch (i)
|
||||
{
|
||||
case 0x1:
|
||||
quality = 1;
|
||||
break;
|
||||
case 0x3:
|
||||
quality = 2;
|
||||
break;
|
||||
case 0x7:
|
||||
quality = 3;
|
||||
break;
|
||||
case 0xf:
|
||||
quality = 4;
|
||||
break;
|
||||
default:
|
||||
quality = 0;
|
||||
}
|
||||
|
||||
|
||||
len = 0;
|
||||
PUTM_TO_PAGE (len, page, "Connection Time: %02ld:%02ld:%02ld\n",
|
||||
((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
|
||||
PUTM_TO_PAGE (len, page, "Connection Time[s]: %ld\n", delta);
|
||||
PUTM_TO_PAGE (len, page, "Asic ID: %s\n",
|
||||
(info->AsicID) ==
|
||||
ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
|
||||
PUTX_TO_PAGE (len, page, "SKU: ", SKUSZ, info->Sku);
|
||||
PUTX_TO_PAGE (len, page, "EUI64: ", EUISZ, info->eui64);
|
||||
PUTD_TO_PAGE (len, page, "DSP version number: ", DSPVERSZ, info->DspVer);
|
||||
PUTX_TO_PAGE (len, page, "Hardware Serial Number: ", HWSERNUMSZ,
|
||||
info->HwSerNum);
|
||||
PUTX_TO_PAGE (len, page, "Caliberation Version: ", CALVERSZ,
|
||||
info->RfCalVer);
|
||||
PUTD_TO_PAGE (len, page, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
|
||||
PUTM_TO_PAGE (len, page, "Media State: %s\n",
|
||||
(info->mediastate) ? "link" : "no link");
|
||||
PUTM_TO_PAGE (len, page, "Connection Status: %s\n",
|
||||
status[((info->ConStat) & 0x7)]);
|
||||
PUTM_TO_PAGE (len, page, "RX packets: %ld\n", info->stats.rx_packets);
|
||||
PUTM_TO_PAGE (len, page, "TX packets: %ld\n", info->stats.tx_packets);
|
||||
PUTM_TO_PAGE (len, page, "RX bytes: %ld\n", info->stats.rx_bytes);
|
||||
PUTM_TO_PAGE (len, page, "TX bytes: %ld\n", info->stats.tx_bytes);
|
||||
PUTM_TO_PAGE (len, page, "Signal Strength: %s\n", signal[strength]);
|
||||
PUTM_TO_PAGE (len, page, "Signal Quality: %s\n", signal[quality]);
|
||||
|
||||
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
ft1000NotifyProc (struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
FT1000_INFO *info;
|
||||
struct proc_dir_entry *ft1000_proc_file;
|
||||
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case NETDEV_CHANGENAME:
|
||||
remove_proc_entry (info->netdevname, info->ft1000_proc_dir);
|
||||
ft1000_proc_file = create_proc_read_entry (dev->name, 0644,
|
||||
info->ft1000_proc_dir,
|
||||
ft1000ReadProc, dev);
|
||||
snprintf (info->netdevname, IFNAMSIZ, "%s", dev->name);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block ft1000_netdev_notifier = {
|
||||
.notifier_call = ft1000NotifyProc
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
ft1000InitProc (struct net_device *dev)
|
||||
{
|
||||
FT1000_INFO *info;
|
||||
struct proc_dir_entry *ft1000_proc_file;
|
||||
info = (FT1000_INFO *) netdev_priv (dev);
|
||||
|
||||
|
||||
info->ft1000_proc_dir = proc_mkdir (FT1000_PROC_DIR, FTNET_PROC);
|
||||
if (info->ft1000_proc_dir == NULL)
|
||||
{
|
||||
remove_proc_entry (FT1000_PROC_DIR, FTNET_PROC);
|
||||
}
|
||||
|
||||
|
||||
ft1000_proc_file =
|
||||
create_proc_read_entry (dev->name, 0644, info->ft1000_proc_dir,
|
||||
ft1000ReadProc, dev);
|
||||
if (ft1000_proc_file == NULL)
|
||||
{
|
||||
remove_proc_entry (info->netdevname, info->ft1000_proc_dir);
|
||||
}
|
||||
|
||||
snprintf (info->netdevname, IFNAMSIZ, "%s", dev->name);
|
||||
register_netdevice_notifier (&ft1000_netdev_notifier);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ft1000CleanupProc (FT1000_INFO * info)
|
||||
{
|
||||
remove_proc_entry (info->netdevname, info->ft1000_proc_dir);
|
||||
remove_proc_entry (FT1000_PROC_DIR, FTNET_PROC);
|
||||
unregister_netdevice_notifier (&ft1000_netdev_notifier);
|
||||
|
||||
return;
|
||||
}
|
349
drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
Normal file
349
drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
Normal file
@ -0,0 +1,349 @@
|
||||
//=====================================================
|
||||
// CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
|
||||
//
|
||||
//
|
||||
// This file is part of Express Card USB Driver
|
||||
//
|
||||
// $Id:
|
||||
//====================================================
|
||||
// 20090926; aelias; removed all compiler warnings; ubuntu 9.04; 2.6.28-15-generic
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include "ft1000_usb.h"
|
||||
|
||||
//#include <linux/sched.h>
|
||||
//#include <linux/ptrace.h>
|
||||
//#include <linux/slab.h>
|
||||
//#include <linux/string.h>
|
||||
//#include <linux/timer.h>
|
||||
//#include <linux/netdevice.h>
|
||||
//#include <linux/ioport.h>
|
||||
//#include <linux/delay.h>
|
||||
//#include <asm/io.h>
|
||||
//#include <asm/system.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER");
|
||||
MODULE_LICENSE("Dual MPL/GPL");
|
||||
MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards");
|
||||
|
||||
|
||||
void *pFileStart;
|
||||
ULONG FileLength;
|
||||
|
||||
#define VENDOR_ID 0x1291 /* Qualcomm vendor id */
|
||||
#define PRODUCT_ID 0x11 /* fake product id */
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id id_table[] = {
|
||||
{USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (usb, id_table);
|
||||
|
||||
extern struct ft1000_device *pdevobj[MAX_NUM_CARDS+2];
|
||||
|
||||
char *getfw (char *fn, int *pimgsz);
|
||||
|
||||
int ft1000_close(struct net_device *net);
|
||||
void dsp_reload (struct ft1000_device *ft1000dev);
|
||||
u16 init_ft1000_netdev(struct ft1000_device *ft1000dev);
|
||||
u16 reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf);
|
||||
int ft1000_poll(void* dev_id);
|
||||
void ft1000_DestroyDevice(struct net_device *dev);
|
||||
u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow);
|
||||
u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx);
|
||||
BOOLEAN gPollingfailed = FALSE;
|
||||
|
||||
void ft1000InitProc(struct net_device *dev);
|
||||
void ft1000CleanupProc(FT1000_INFO *info);
|
||||
int ft1000_poll_thread(void *arg);
|
||||
|
||||
int ft1000_poll_thread(void *arg)
|
||||
{
|
||||
int ret = STATUS_SUCCESS;
|
||||
|
||||
while(!kthread_should_stop() )
|
||||
{
|
||||
msleep(10);
|
||||
if ( ! gPollingfailed )
|
||||
{
|
||||
ret = ft1000_poll(arg);
|
||||
if ( ret != STATUS_SUCCESS )
|
||||
{
|
||||
DEBUG("ft1000_poll_thread: polling failed\n");
|
||||
gPollingfailed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//DEBUG("returned from polling thread\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_probe
|
||||
//
|
||||
// Parameters: struct usb_interface *interface - passed by USB core
|
||||
// struct usb_device_id *id - passed by USB core
|
||||
// Returns: 0 - success
|
||||
//
|
||||
// Description: This function is invoked when the express card is plugged in
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int ft1000_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_host_interface *iface_desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct usb_device *dev;
|
||||
unsigned numaltsetting;
|
||||
int i;
|
||||
|
||||
struct ft1000_device *ft1000dev;
|
||||
FT1000_INFO *pft1000info;
|
||||
|
||||
if(!(ft1000dev = kmalloc(sizeof(struct ft1000_device), GFP_KERNEL)))
|
||||
{
|
||||
printk("out of memory allocating device structure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(ft1000dev, 0, sizeof(*ft1000dev));
|
||||
|
||||
//get usb device
|
||||
dev = interface_to_usbdev(interface);
|
||||
DEBUG("ft1000_probe: usb device descriptor info:\n");
|
||||
DEBUG("ft1000_probe: number of configuration is %d\n", dev->descriptor.bNumConfigurations);
|
||||
|
||||
ft1000dev->dev = dev;
|
||||
ft1000dev->status = 0;
|
||||
ft1000dev->net = NULL;
|
||||
//ft1000dev->device_lock = SPIN_LOCK_UNLOCKED;
|
||||
spin_lock_init(&ft1000dev->device_lock);
|
||||
ft1000dev->tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
ft1000dev->rx_urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
|
||||
|
||||
DEBUG("ft1000_probe is called\n");
|
||||
numaltsetting = interface->num_altsetting;
|
||||
DEBUG("ft1000_probe: number of alt settings is :%d\n",numaltsetting);
|
||||
iface_desc = interface->cur_altsetting;
|
||||
DEBUG("ft1000_probe: number of endpoints is %d\n", iface_desc->desc.bNumEndpoints);
|
||||
DEBUG("ft1000_probe: descriptor type is %d\n", iface_desc->desc.bDescriptorType);
|
||||
DEBUG("ft1000_probe: interface number is %d\n", iface_desc->desc.bInterfaceNumber);
|
||||
DEBUG("ft1000_probe: alternatesetting is %d\n", iface_desc->desc.bAlternateSetting);
|
||||
DEBUG("ft1000_probe: interface class is %d\n", iface_desc->desc.bInterfaceClass);
|
||||
DEBUG("ft1000_probe: control endpoint info:\n");
|
||||
DEBUG("ft1000_probe: descriptor0 type -- %d\n", iface_desc->endpoint[0].desc.bmAttributes);
|
||||
DEBUG("ft1000_probe: descriptor1 type -- %d\n", iface_desc->endpoint[1].desc.bmAttributes);
|
||||
DEBUG("ft1000_probe: descriptor2 type -- %d\n", iface_desc->endpoint[2].desc.bmAttributes);
|
||||
|
||||
for (i=0; i< iface_desc->desc.bNumEndpoints;i++ )
|
||||
{
|
||||
endpoint = (struct usb_endpoint_descriptor *)&iface_desc->endpoint[i].desc;
|
||||
DEBUG("endpoint %d\n", i);
|
||||
DEBUG("bEndpointAddress=%x, bmAttributes=%x\n", endpoint->bEndpointAddress, endpoint->bmAttributes);
|
||||
if ( (endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
|
||||
{
|
||||
ft1000dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
|
||||
DEBUG("ft1000_probe: in: %d\n", endpoint->bEndpointAddress);
|
||||
}
|
||||
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
|
||||
{
|
||||
ft1000dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
|
||||
DEBUG("ft1000_probe: out: %d\n", endpoint->bEndpointAddress);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("bulk_in=%d, bulk_out=%d\n", ft1000dev->bulk_in_endpointAddr, ft1000dev->bulk_out_endpointAddr);
|
||||
|
||||
//read DSP image
|
||||
pFileStart = (void*)getfw("/etc/flarion/ft3000.img", &FileLength);
|
||||
|
||||
if (pFileStart == NULL )
|
||||
{
|
||||
DEBUG ("ft1000_probe: Read DSP image failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//for ( i=0; i< MAX_NUM_CARDS+2; i++)
|
||||
// pdevobj[i] = NULL;
|
||||
|
||||
//download dsp image
|
||||
DEBUG("ft1000_probe: start downloading dsp image...\n");
|
||||
init_ft1000_netdev(ft1000dev);
|
||||
pft1000info = (FT1000_INFO *) netdev_priv (ft1000dev->net);
|
||||
|
||||
// DEBUG("In probe: pft1000info=%x\n", pft1000info); // aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct FT1000_INFO *???
|
||||
DEBUG("In probe: pft1000info=%x\n", (unsigned int)pft1000info); // aelias [+] reason: up
|
||||
|
||||
dsp_reload(ft1000dev);
|
||||
gPollingfailed = FALSE; //mbelian
|
||||
pft1000info->pPollThread = kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll");
|
||||
msleep(500); //mbelian
|
||||
|
||||
|
||||
if ( pft1000info->DSP_loading )
|
||||
{
|
||||
DEBUG("ERROR!!!! RETURN FROM ft1000_probe **********************\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!pft1000info->CardReady)
|
||||
{
|
||||
if ( gPollingfailed )
|
||||
{
|
||||
if ( pft1000info->pPollThread )
|
||||
{
|
||||
kthread_stop(pft1000info->pPollThread );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
msleep(100);
|
||||
DEBUG("ft1000_probe::Waiting for Card Ready\n");
|
||||
}
|
||||
|
||||
|
||||
//initialize network device
|
||||
DEBUG("ft1000_probe::Card Ready!!!! Registering network device\n");
|
||||
|
||||
reg_ft1000_netdev(ft1000dev, interface);
|
||||
|
||||
pft1000info->NetDevRegDone = 1;
|
||||
|
||||
ft1000InitProc(ft1000dev->net);// +mbelian
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: ft1000_disconnect
|
||||
//
|
||||
// Parameters: struct usb_interface *interface - passed by USB core
|
||||
//
|
||||
// Returns: 0 - success
|
||||
//
|
||||
// Description: This function is invoked when the express card is plugged out
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static void ft1000_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
FT1000_INFO *pft1000info;
|
||||
|
||||
DEBUG("ft1000_disconnect is called\n");
|
||||
|
||||
pft1000info = (PFT1000_INFO)usb_get_intfdata(interface);
|
||||
// DEBUG("In disconnect pft1000info=%x\n", pft1000info); // aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct FT1000_INFO *???
|
||||
DEBUG("In disconnect pft1000info=%x\n", (unsigned int) pft1000info); // aelias [+] reason: up
|
||||
|
||||
|
||||
|
||||
if (pft1000info)
|
||||
{
|
||||
ft1000CleanupProc(pft1000info); //+mbelian
|
||||
if ( pft1000info->pPollThread )
|
||||
{
|
||||
kthread_stop(pft1000info->pPollThread );
|
||||
}
|
||||
|
||||
DEBUG("ft1000_disconnect: threads are terminated\n");
|
||||
|
||||
if (pft1000info->pFt1000Dev->net)
|
||||
{
|
||||
DEBUG("ft1000_disconnect: destroy char driver\n");
|
||||
ft1000_DestroyDevice(pft1000info->pFt1000Dev->net);
|
||||
//DEBUG("ft1000_disconnect: calling ft1000_close\n");
|
||||
//ft1000_close(pft1000info->pFt1000Dev->net);
|
||||
//DEBUG("ft1000_disconnect: ft1000_close is called\n");
|
||||
unregister_netdev(pft1000info->pFt1000Dev->net);
|
||||
DEBUG("ft1000_disconnect: network device unregisterd\n");
|
||||
free_netdev(pft1000info->pFt1000Dev->net);
|
||||
|
||||
}
|
||||
|
||||
usb_free_urb(pft1000info->pFt1000Dev->rx_urb);
|
||||
usb_free_urb(pft1000info->pFt1000Dev->tx_urb);
|
||||
|
||||
DEBUG("ft1000_disconnect: urb freed\n");
|
||||
|
||||
kfree(pft1000info->pFt1000Dev); //+mbelian
|
||||
}
|
||||
|
||||
//terminate other kernel threads
|
||||
//in multiple instances case, first find the device
|
||||
//in the link list
|
||||
/**if (pPollThread)
|
||||
{
|
||||
kthread_stop(pPollThread);
|
||||
DEBUG("Polling thread is killed \n");
|
||||
}**/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct usb_driver ft1000_usb_driver = {
|
||||
//.owner = THIS_MODULE,
|
||||
.name = "ft1000usb",
|
||||
.probe = ft1000_probe,
|
||||
.disconnect = ft1000_disconnect,
|
||||
.id_table = id_table,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: usb_ft1000_init
|
||||
//
|
||||
// Parameters: none
|
||||
//
|
||||
// Returns: 0 - success
|
||||
//
|
||||
// Description: The entry point of the module, register the usb driver
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int __init usb_ft1000_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DEBUG("Initialize and register the driver\n");
|
||||
|
||||
ret = usb_register(&ft1000_usb_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: usb_ft1000_exit
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description: Moudle unload function, deregister usb driver
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static void __exit usb_ft1000_exit(void)
|
||||
{
|
||||
DEBUG("Deregister the driver\n");
|
||||
usb_deregister(&ft1000_usb_driver);
|
||||
}
|
||||
|
||||
module_init (usb_ft1000_init);
|
||||
module_exit (usb_ft1000_exit);
|
||||
|
||||
|
609
drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
Normal file
609
drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
Normal file
@ -0,0 +1,609 @@
|
||||
#ifndef _FT1000_USB_H_
|
||||
#define _FT1000_USB_H_
|
||||
|
||||
/*Jim*/
|
||||
#include "ft1000_ioctl.h"
|
||||
#define FT1000_DRV_VER 0x01010403
|
||||
|
||||
#define MODESZ 2
|
||||
#define MAX_NUM_APP 6
|
||||
#define MAX_MSG_LIMIT 200
|
||||
#define NUM_OF_FREE_BUFFERS 1500
|
||||
|
||||
// Driver message types
|
||||
#define MEDIA_STATE 0x0010
|
||||
#define DSP_PROVISION 0x0030
|
||||
#define DSP_INIT_MSG 0x0050
|
||||
#define DSP_STORE_INFO 0x0070
|
||||
#define DSP_GET_INFO 0x0071
|
||||
#define GET_DRV_ERR_RPT_MSG 0x0073
|
||||
#define RSP_DRV_ERR_RPT_MSG 0x0074
|
||||
|
||||
|
||||
// Size of DPRAM Command
|
||||
#define MAX_CMD_SQSIZE 1780
|
||||
#define SLOWQ_TYPE 0
|
||||
#define PSEUDOSZ 16
|
||||
#define DSP_QID_OFFSET 4
|
||||
|
||||
|
||||
// MEMORY MAP FOR ELECTRABUZZ ASIC
|
||||
#define FT1000_REG_DFIFO_STAT 0x0008 // Downlink FIFO status register
|
||||
#define FT1000_REG_DPRAM_DATA 0x000C // DPRAM VALUE in DPRAM ADDR
|
||||
|
||||
#define FT1000_DSP_LED 0xFFA // dsp led status for PAD device
|
||||
|
||||
#define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device
|
||||
#define FT1000_MAG_DSP_LED_INDX 0x1 // dsp led status for PAD device
|
||||
|
||||
#define SUCCESS 0x00
|
||||
|
||||
|
||||
#define DRIVERID 0x00
|
||||
|
||||
// Driver Error Messages for DSP
|
||||
#define DSP_CONDRESET_INFO 0x7ef2
|
||||
#define DSP_HB_INFO 0x7ef0
|
||||
|
||||
// Magnemite specific defines
|
||||
#define hi_mag 0x6968 // Byte swap hi to avoid additional system call
|
||||
#define ho_mag 0x6f68 // Byte swap ho to avoid additional system call
|
||||
|
||||
|
||||
|
||||
typedef struct _MEDIAMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u16 state;
|
||||
u32 ip_addr;
|
||||
u32 net_mask;
|
||||
u32 gateway;
|
||||
u32 dns_1;
|
||||
u32 dns_2;
|
||||
} __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG;
|
||||
|
||||
typedef struct _DSPINITMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u8 DspVer[DSPVERSZ]; // DSP version number
|
||||
u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
|
||||
u8 Sku[SKUSZ]; // SKU
|
||||
u8 eui64[EUISZ]; // EUI64
|
||||
u8 ProductMode[MODESZ]; // Product Mode (Market/Production)
|
||||
u8 RfCalVer[CALVERSZ]; // Rf Calibration version
|
||||
u8 RfCalDate[CALDATESZ]; // Rf Calibration date
|
||||
} __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG;
|
||||
|
||||
|
||||
typedef struct _APP_INFO_BLOCK
|
||||
{
|
||||
u32 nTxMsg; // DPRAM msg sent to DSP with app_id
|
||||
u32 nRxMsg; // DPRAM msg rcv from dsp with app_id
|
||||
u32 nTxMsgReject; // DPRAM msg rejected due to DSP doorbell set
|
||||
u32 nRxMsgMiss; // DPRAM msg dropped due to overflow
|
||||
u32 fileobject; // Application's file object
|
||||
u16 app_id; // Application id
|
||||
int DspBCMsgFlag;
|
||||
int NumOfMsg; // number of messages queued up
|
||||
wait_queue_head_t wait_dpram_msg;
|
||||
struct list_head app_sqlist; // link list of msgs for applicaton on slow queue
|
||||
} APP_INFO_BLOCK, *PAPP_INFO_BLOCK;
|
||||
|
||||
typedef struct _PROV_RECORD {
|
||||
struct list_head list;
|
||||
u8 *pprov_data;
|
||||
} PROV_RECORD, *PPROV_RECORD;
|
||||
|
||||
/*end of Jim*/
|
||||
|
||||
#define DEBUG(args...) printk(KERN_INFO args)
|
||||
|
||||
#define UCHAR u8
|
||||
#define USHORT u16
|
||||
#define ULONG u32
|
||||
#define BOOLEAN u8
|
||||
#define PULONG u32 *
|
||||
#define PUSHORT u16 *
|
||||
#define PUCHAR u8 *
|
||||
#define PCHAR u8 *
|
||||
#define UINT u32
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define STATUS_SUCCESS 0
|
||||
#define STATUS_FAILURE 0x1001
|
||||
|
||||
#define FT1000_STATUS_CLOSING 0x01
|
||||
|
||||
#define LARGE_TIMEOUT 5000
|
||||
|
||||
#define MAX_DSP_SESS_REC 1024
|
||||
|
||||
#define MAX_NUM_CARDS 32
|
||||
|
||||
#define DSPVERSZ 4
|
||||
#define HWSERNUMSZ 16
|
||||
#define SKUSZ 20
|
||||
#define EUISZ 8
|
||||
#define CALVERSZ 2
|
||||
#define CALDATESZ 6
|
||||
#define MODESZ 2
|
||||
|
||||
#define DSPID 0x20
|
||||
#define HOSTID 0x10
|
||||
|
||||
#define DSPOAM 0x80
|
||||
#define DSPAIRID 0x90
|
||||
|
||||
#define DRIVERID 0x00
|
||||
#define FMM 0x10
|
||||
#define NETWORKID 0x20
|
||||
#define AUTOLNCHID 0x30
|
||||
#define DSPLPBKID 0x40
|
||||
|
||||
#define DSPBCMSGID 0x10
|
||||
|
||||
#define ENET_MAX_SIZE 1514
|
||||
#define ENET_HEADER_SIZE 14
|
||||
|
||||
|
||||
#define CIS_NET_ADDR_OFFSET 0xff0
|
||||
|
||||
#define MEM_TAG 'FLRN'
|
||||
// MAGNEMITE specific
|
||||
|
||||
#define FT1000_REG_MAG_UFDR 0x0000 // Uplink FIFO Data Register.
|
||||
|
||||
#define FT1000_REG_MAG_UFDRL 0x0000 // Uplink FIFO Data Register low-word.
|
||||
|
||||
#define FT1000_REG_MAG_UFDRH 0x0002 // Uplink FIFO Data Register high-word.
|
||||
|
||||
#define FT1000_REG_MAG_UFER 0x0004 // Uplink FIFO End Register
|
||||
|
||||
#define FT1000_REG_MAG_UFSR 0x0006 // Uplink FIFO Status Register
|
||||
|
||||
#define FT1000_REG_MAG_DFR 0x0008 // Downlink FIFO Register
|
||||
|
||||
#define FT1000_REG_MAG_DFRL 0x0008 // Downlink FIFO Register low-word
|
||||
|
||||
#define FT1000_REG_MAG_DFRH 0x000a // Downlink FIFO Register high-word
|
||||
|
||||
#define FT1000_REG_MAG_DFSR 0x000c // Downlink FIFO Status Register
|
||||
|
||||
#define FT1000_REG_MAG_DPDATA 0x0010 // Dual Port RAM Indirect Data Register
|
||||
|
||||
#define FT1000_REG_MAG_DPDATAL 0x0010 // Dual Port RAM Indirect Data Register low-word
|
||||
|
||||
#define FT1000_REG_MAG_DPDATAH 0x0012 // Dual Port RAM Indirect Data Register high-word
|
||||
|
||||
#define FT1000_REG_MAG_WATERMARK 0x002c // Supv. Control Reg. LLC register
|
||||
|
||||
#define FT1000_REG_MAG_VERSION 0x0030 // LLC Version LLC register
|
||||
|
||||
|
||||
|
||||
// Common
|
||||
|
||||
#define FT1000_REG_DPRAM_ADDR 0x000E // DPRAM ADDRESS when card in IO mode
|
||||
|
||||
#define FT1000_REG_SUP_CTRL 0x0020 // Supv. Control Reg. LLC register
|
||||
|
||||
#define FT1000_REG_SUP_STAT 0x0022 // Supv. Status Reg LLC register
|
||||
|
||||
#define FT1000_REG_RESET 0x0024 // Reset Reg LLC register
|
||||
|
||||
#define FT1000_REG_SUP_ISR 0x0026 // Supv ISR LLC register
|
||||
|
||||
#define FT1000_REG_SUP_IMASK 0x0028 // Supervisor Interrupt Mask LLC register
|
||||
|
||||
#define FT1000_REG_DOORBELL 0x002a // Door Bell Reg LLC register
|
||||
|
||||
#define FT1000_REG_ASIC_ID 0x002e // ASIC Identification Number
|
||||
|
||||
// (Electrabuzz=0 Magnemite=TBD)
|
||||
|
||||
|
||||
|
||||
// DSP doorbells
|
||||
|
||||
#define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has
|
||||
|
||||
// data for host in DPRAM SlowQ
|
||||
|
||||
#define FT1000_DB_DNLD_RX 0x0002 // Downloader handshake doorbell
|
||||
|
||||
#define FT1000_ASIC_RESET_REQ 0x0004
|
||||
|
||||
#define FT1000_DSP_ASIC_RESET 0x0008
|
||||
|
||||
|
||||
|
||||
#define FT1000_DB_COND_RESET 0x0010
|
||||
|
||||
|
||||
|
||||
// Host doorbells
|
||||
|
||||
#define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has
|
||||
|
||||
// data for DSP in DPRAM.
|
||||
|
||||
#define FT1000_DB_DNLD_TX 0x0200 // Downloader handshake doorbell
|
||||
|
||||
#define FT1000_ASIC_RESET_DSP 0x0400
|
||||
|
||||
#define FT1000_DB_HB 0x1000 // this value indicates that supervisor
|
||||
|
||||
|
||||
|
||||
// Electrabuzz specific DPRAM mapping // has a heartbeat message for DSP.
|
||||
|
||||
#define FT1000_DPRAM_BASE 0x1000 // 0x0000 to 0x07FF DPRAM 2Kx16 - R/W from PCMCIA or DSP
|
||||
|
||||
#define FT1000_DPRAM_TX_BASE 0x1002 // TX AREA (SlowQ)
|
||||
|
||||
#define FT1000_DPRAM_RX_BASE 0x1800 // RX AREA (SlowQ)
|
||||
|
||||
#define FT1000_DPRAM_SIZE 0x1000 // 4K bytes
|
||||
|
||||
|
||||
|
||||
#define FT1000_DRV_DEBUG 0x17E0 // Debug area for driver
|
||||
|
||||
#define FT1000_FIFO_LEN 0x17FC // total length for DSP FIFO tracking
|
||||
|
||||
#define FT1000_HI_HO 0x17FE // heartbeat with HI/HO
|
||||
|
||||
#define FT1000_DSP_STATUS 0x1FFE // dsp status - non-zero is a request to reset dsp
|
||||
|
||||
|
||||
|
||||
#define FT1000_DSP_CON_STATE 0x1FF8 // DSP Connection Status Info
|
||||
|
||||
#define FT1000_DSP_LEDS 0x1FFA // DSP LEDS for rcv pwr strength, Rx data, Tx data
|
||||
|
||||
#define DSP_TIMESTAMP 0x1FFC // dsp timestamp
|
||||
|
||||
#define DSP_TIMESTAMP_DIFF 0x1FFA // difference of dsp timestamp in DPRAM and Pseudo header.
|
||||
|
||||
|
||||
|
||||
#define FT1000_DPRAM_FEFE 0x1002 // Dsp Downloader handshake location
|
||||
|
||||
|
||||
|
||||
#define FT1000_DSP_TIMER0 0x1FF0
|
||||
|
||||
#define FT1000_DSP_TIMER1 0x1FF2
|
||||
|
||||
#define FT1000_DSP_TIMER2 0x1FF4
|
||||
|
||||
#define FT1000_DSP_TIMER3 0x1FF6
|
||||
|
||||
|
||||
|
||||
// MEMORY MAP FOR MAGNEMITE
|
||||
|
||||
#define FT1000_DPRAM_MAG_TX_BASE 0x0000 // TX AREA (SlowQ)
|
||||
|
||||
#define FT1000_DPRAM_MAG_RX_BASE 0x0200 // RX AREA (SlowQ)
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking
|
||||
|
||||
#define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index
|
||||
|
||||
#define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO
|
||||
|
||||
#define FT1000_MAG_HI_HO_INDX 0x0 // high-word index
|
||||
|
||||
#define FT1000_MAG_DSP_LEDS 0x3FE // dsp led status for PAD device
|
||||
|
||||
#define FT1000_MAG_DSP_LEDS_INDX 0x1 // dsp led status for PAD device
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info
|
||||
|
||||
#define FT1000_MAG_DSP_CON_STATE_INDX 0x0 // DSP Connection Status Info
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator
|
||||
|
||||
#define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER0 0x3FC
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER0_INDX 0x1
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER1 0x3FC
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER1_INDX 0x0
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER2 0x3FD
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER2_INDX 0x1
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER3 0x3FD
|
||||
|
||||
#define FT1000_MAG_DSP_TIMER3_INDX 0x0
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_TOTAL_LEN 0x200
|
||||
|
||||
#define FT1000_MAG_TOTAL_LEN_INDX 0x1
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_PH_LEN 0x200
|
||||
|
||||
#define FT1000_MAG_PH_LEN_INDX 0x0
|
||||
|
||||
|
||||
|
||||
#define FT1000_MAG_PORT_ID 0x201
|
||||
|
||||
#define FT1000_MAG_PORT_ID_INDX 0x0
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
// Constants for the FT1000_REG_SUP_ISR
|
||||
|
||||
//
|
||||
|
||||
// Indicate the cause of an interrupt.
|
||||
|
||||
//
|
||||
|
||||
// SUPERVISOR ISR BIT MAPS
|
||||
|
||||
|
||||
|
||||
#define ISR_EMPTY (UCHAR)0x00 // no bits set in ISR
|
||||
|
||||
#define ISR_DOORBELL_ACK (UCHAR)0x01 // the doorbell i sent has been recieved.
|
||||
|
||||
#define ISR_DOORBELL_PEND (UCHAR)0x02 // doorbell for me
|
||||
|
||||
#define ISR_RCV (UCHAR)0x04 // packet received with no errors
|
||||
|
||||
#define ISR_WATERMARK (UCHAR)0x08 //
|
||||
|
||||
|
||||
|
||||
// Interrupt mask register defines
|
||||
|
||||
// note these are different from the ISR BIT MAPS.
|
||||
|
||||
#define ISR_MASK_NONE 0x0000
|
||||
|
||||
#define ISR_MASK_DOORBELL_ACK 0x0001
|
||||
|
||||
#define ISR_MASK_DOORBELL_PEND 0x0002
|
||||
|
||||
#define ISR_MASK_RCV 0x0004
|
||||
|
||||
#define ISR_MASK_WATERMARK 0x0008 // Normally we will only mask the watermark interrupt when we want to enable interrupts.
|
||||
|
||||
#define ISR_MASK_ALL 0xffff
|
||||
|
||||
|
||||
|
||||
#define HOST_INTF_LE 0x0000 // Host interface little endian
|
||||
|
||||
#define HOST_INTF_BE 0x0001 // Host interface big endian
|
||||
|
||||
|
||||
|
||||
#define ISR_DEFAULT_MASK 0x7ff9
|
||||
|
||||
|
||||
|
||||
#define hi 0x6869
|
||||
|
||||
#define ho 0x686f
|
||||
|
||||
|
||||
|
||||
#define FT1000_ASIC_RESET 0x80 // COR value for soft reset to PCMCIA core
|
||||
|
||||
#define FT1000_ASIC_BITS 0x51 // Bits set in COR register under normal operation
|
||||
|
||||
#define FT1000_ASIC_MAG_BITS 0x55 // Bits set in COR register under normal operation
|
||||
|
||||
|
||||
|
||||
#define FT1000_COR_OFFSET 0x100
|
||||
|
||||
|
||||
|
||||
#define ELECTRABUZZ_ID 0 // ASIC ID for ELECTRABUZZ
|
||||
|
||||
#define MAGNEMITE_ID 0x1a01 // ASIC ID for MAGNEMITE
|
||||
|
||||
|
||||
|
||||
// Maximum times trying to get ASIC out of reset
|
||||
|
||||
#define MAX_ASIC_RESET_CNT 20
|
||||
|
||||
|
||||
|
||||
#define DSP_RESET_BIT 0x1
|
||||
|
||||
#define ASIC_RESET_BIT 0x2
|
||||
|
||||
#define DSP_UNENCRYPTED 0x4
|
||||
|
||||
#define DSP_ENCRYPTED 0x8
|
||||
|
||||
#define EFUSE_MEM_DISABLE 0x0040
|
||||
|
||||
|
||||
#define MAX_BUF_SIZE 4096
|
||||
|
||||
|
||||
#if 0 //Removed by Jim
|
||||
typedef struct _PSEUDO_HDR
|
||||
|
||||
{
|
||||
|
||||
unsigned short length;
|
||||
|
||||
unsigned char source;
|
||||
|
||||
unsigned char destination;
|
||||
|
||||
unsigned char portdest;
|
||||
|
||||
unsigned char portsrc;
|
||||
|
||||
unsigned short sh_str_id;
|
||||
|
||||
unsigned char control;
|
||||
|
||||
unsigned char rsvd1;
|
||||
|
||||
unsigned char seq_num;
|
||||
|
||||
unsigned char rsvd2;
|
||||
|
||||
unsigned short qos_class;
|
||||
|
||||
unsigned short checksum;
|
||||
|
||||
|
||||
|
||||
} PSEUDO_HDR, *PPSEUDO_HDR;
|
||||
#endif //end of Jim
|
||||
|
||||
typedef struct _DRVMSG {
|
||||
PSEUDO_HDR pseudo;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u8 data[0];
|
||||
} __attribute__ ((packed)) DRVMSG, *PDRVMSG;
|
||||
|
||||
struct ft1000_device
|
||||
{
|
||||
struct usb_device *dev;
|
||||
struct net_device *net;
|
||||
spinlock_t device_lock;
|
||||
|
||||
u32 status;
|
||||
|
||||
wait_queue_head_t control_wait;
|
||||
|
||||
struct urb *rx_urb;
|
||||
struct urb *tx_urb;
|
||||
|
||||
u8 tx_buf[MAX_BUF_SIZE];
|
||||
u8 rx_buf[MAX_BUF_SIZE];
|
||||
|
||||
u8 bulk_in_endpointAddr;
|
||||
u8 bulk_out_endpointAddr;
|
||||
|
||||
//struct ft1000_ethernet_configuration configuration;
|
||||
|
||||
// struct net_device_stats stats; //mbelian
|
||||
} __attribute__ ((packed));
|
||||
|
||||
typedef struct _FT1000_INFO {
|
||||
struct ft1000_device *pFt1000Dev;
|
||||
struct net_device_stats stats;
|
||||
|
||||
struct task_struct *pPollThread;
|
||||
|
||||
unsigned char fcodeldr;
|
||||
unsigned char bootmode;
|
||||
unsigned char usbboot;
|
||||
unsigned short dspalive;
|
||||
u16 ASIC_ID;
|
||||
BOOLEAN fProvComplete;
|
||||
BOOLEAN fCondResetPend;
|
||||
BOOLEAN fAppMsgPend;
|
||||
char *pfwimg;
|
||||
int fwimgsz;
|
||||
u16 DrvErrNum;
|
||||
u8 *pTestImage;
|
||||
u16 AsicID;
|
||||
unsigned long TestImageIndx;
|
||||
unsigned long TestImageSz;
|
||||
u8 TestImageEnable;
|
||||
u8 TestImageReady;
|
||||
int ASICResetNum;
|
||||
int DspAsicReset;
|
||||
int PktIntfErr;
|
||||
int DSPResetNum;
|
||||
int NumIOCTLBufs;
|
||||
int IOCTLBufLvl;
|
||||
int DeviceCreated;
|
||||
int CardReady;
|
||||
int DSP_loading;
|
||||
int NetDevRegDone;
|
||||
u8 CardNumber;
|
||||
u8 DeviceName[15];
|
||||
int DeviceMajor;
|
||||
int registered;
|
||||
int mediastate;
|
||||
int dhcpflg;
|
||||
u16 packetseqnum;
|
||||
u8 squeseqnum; // sequence number on slow queue
|
||||
spinlock_t dpram_lock;
|
||||
spinlock_t fifo_lock;
|
||||
u16 CurrentInterruptEnableMask;
|
||||
int InterruptsEnabled;
|
||||
u16 fifo_cnt;
|
||||
u8 DspVer[DSPVERSZ]; // DSP version number
|
||||
u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number
|
||||
u8 Sku[SKUSZ]; // SKU
|
||||
u8 eui64[EUISZ]; // EUI64
|
||||
time_t ConTm; // Connection Time
|
||||
u8 ProductMode[MODESZ];
|
||||
u8 RfCalVer[CALVERSZ];
|
||||
u8 RfCalDate[CALDATESZ];
|
||||
u16 DSP_TIME[4];
|
||||
u16 ProgSnr;
|
||||
u16 LedStat; //mbelian
|
||||
u16 ConStat; //mbelian
|
||||
u16 ProgConStat;
|
||||
struct list_head prov_list;
|
||||
int appcnt;
|
||||
APP_INFO_BLOCK app_info[MAX_NUM_APP]; //Added by Jim
|
||||
u16 DSPInfoBlklen;
|
||||
u16 DrvMsgPend;
|
||||
int (*ft1000_reset)(struct net_device *dev);
|
||||
u16 DSPInfoBlk[MAX_DSP_SESS_REC];
|
||||
union {
|
||||
u16 Rec[MAX_DSP_SESS_REC];
|
||||
u32 MagRec[MAX_DSP_SESS_REC/2];
|
||||
} DSPSess;
|
||||
unsigned short tempbuf[32];
|
||||
char netdevname[IFNAMSIZ];
|
||||
struct proc_dir_entry *ft1000_proc_dir; //mbelian
|
||||
} FT1000_INFO, *PFT1000_INFO;
|
||||
|
||||
|
||||
typedef struct _DPRAM_BLK {
|
||||
struct list_head list;
|
||||
u16 *pbuffer;
|
||||
} __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK;
|
||||
|
||||
|
||||
#endif
|
BIN
drivers/staging/ft1000/ft1000-usb/ft3000.img
Normal file
BIN
drivers/staging/ft1000/ft1000-usb/ft3000.img
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user