Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Marek Belisko and committed by
Greg Kroah-Hartman
f7c1be0c 027360c5

+11101
+2
drivers/staging/Kconfig
··· 165 165 166 166 source "drivers/staging/bcm/Kconfig" 167 167 168 + source "drivers/staging/ft1000/Kconfig" 169 + 168 170 endif # !STAGING_EXCLUDE_BUILD 169 171 endif # STAGING
+1
drivers/staging/Makefile
··· 63 63 obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/ 64 64 obj-$(CONFIG_USB_ENESTORAGE) += keucr/ 65 65 obj-$(CONFIG_BCM_WIMAX) += bcm/ 66 + obj-$(CONFIG_FT1000) += ft1000/
+22
drivers/staging/ft1000/Kconfig
··· 1 + config FT1000 2 + tristate "Drivers for Flarion ft1000 devices" 3 + 4 + if FT1000 5 + 6 + config FT1000_USB 7 + tristate "Driver for ft1000 usb devices." 8 + depends on USB 9 + depends on NET 10 + help 11 + Say Y if you want to have support for Qleadtek FLASH-OFDM USB Modem [LR7F04], 12 + Qleadtek Express Card or Leadtek Multi-band modem HSDPA. 13 + 14 + config FT1000_PCMCIA 15 + tristate "Driver for ft1000 pcmcia device." 16 + depends on PCMCIA 17 + depends on NET 18 + help 19 + Say Y if you want to have support for Flarion card also called 20 + Multimedia Net Card. 21 + 22 + endif
+3
drivers/staging/ft1000/Makefile
··· 1 + obj-$(CONFIG_FT1000_USB) += ft1000-usb/ 2 + obj-$(CONFIG_FT1000_PCMCIA) += ft1000-pcmcia/ 3 +
+9
drivers/staging/ft1000/TODO
··· 1 + TODO: 2 + - checkpatch.pl cleanups 3 + - coding style 4 + - sparse fixes 5 + - adapt to latest usb and pcmcia api changes 6 + - change firmware loading for usb driver to proper kernel method (request_firmware) 7 + 8 + Please send patches to Greg Kroah-Hartman <greg@kroah.com> and 9 + Cc: Marek Belisko <marek.belisko@gmail.com>
+3
drivers/staging/ft1000/ft1000-pcmcia/Makefile
··· 1 + obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o 2 + ft1000_pcmcia-objs := ft1000_hw.o ft1000_dnld.o ft1000_proc.o ft1000_cs.o 3 +
+158
drivers/staging/ft1000/ft1000-pcmcia/boot.h
··· 1 + //--------------------------------------------------------------------------- 2 + // FT1000 driver for Flarion Flash OFDM NIC Device 3 + // 4 + // Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + // 6 + // This program is free software; you can redistribute it and/or modify it 7 + // under the terms of the GNU General Public License as published by the Free 8 + // Software Foundation; either version 2 of the License, or (at your option) any 9 + // later version. This program is distributed in the hope that it will be useful, 10 + // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + // more details. You should have received a copy of the GNU General Public 13 + // License along with this program; if not, write to the 14 + // Free Software Foundation, Inc., 59 Temple Place - 15 + // Suite 330, Boston, MA 02111-1307, USA. 16 + //--------------------------------------------------------------------------- 17 + // 18 + // File: boot.h 19 + // 20 + // Description: boatloader 21 + // 22 + // History: 23 + // 1/11/05 Whc Ported to Linux. 24 + // 25 + //--------------------------------------------------------------------------- 26 + #ifndef _BOOTH_ 27 + #define _BOOTH_ 28 + 29 + // Official bootloader 30 + unsigned char bootimage [] = { 31 + 0x00,0x00,0x01,0x5E,0x00,0x00 32 + ,0x00,0x00,0x00,0x00,0x02,0xD7 33 + ,0x00,0x00,0x01,0x5E,0x46,0xB3 34 + ,0xE6,0x02,0x00,0x98,0xE6,0x8C 35 + ,0x00,0x98,0xFB,0x92,0xFF,0xFF 36 + ,0x98,0xFB,0x94,0xFF,0xFF,0x98 37 + ,0xFB,0x06,0x08,0x00,0x98,0xFB 38 + ,0x96,0x84,0x00,0x98,0xFB,0x08 39 + ,0x1C,0x00,0x98,0xFB,0x51,0x25 40 + ,0x10,0x1C,0x00,0xE6,0x51,0x01 41 + ,0x07,0xFD,0x4C,0xFF,0x20,0xF5 42 + ,0x51,0x02,0x20,0x08,0x00,0x4C 43 + ,0xFF,0x20,0x3C,0x00,0xC0,0x64 44 + ,0x98,0xC0,0x66,0x98,0xC0,0x68 45 + ,0x98,0xC0,0x6A,0x98,0xC0,0x6C 46 + ,0x98,0x90,0x08,0x90,0x09,0x90 47 + ,0x0A,0x90,0x0B,0x90,0x0C,0x90 48 + ,0x0D,0x90,0x0E,0x90,0x0F,0x90 49 + ,0x04,0x90,0x06,0xFB,0x51,0x22 50 + ,0x16,0x08,0x03,0xFB,0x51,0x52 51 + ,0x16,0x08,0x04,0xFB,0x51,0x24 52 + ,0x2B,0x08,0x06,0xFB,0x51,0x54 53 + ,0x2B,0x08,0x07,0xFB,0x51,0x24 54 + ,0x2B,0x08,0x09,0xFB,0x51,0x54 55 + ,0x2B,0x08,0x0A,0xFB,0x51,0x12 56 + ,0x16,0x08,0x0C,0xFB,0x51,0x52 57 + ,0x16,0x08,0x0D,0x78,0x00,0x00 58 + ,0x00,0x16,0x00,0x00,0xEC,0x31 59 + ,0xAE,0x00,0x00,0x81,0x4C,0x0F 60 + ,0xE6,0x43,0xFF,0xEC,0x31,0x4E 61 + ,0x00,0x00,0x91,0xEC,0x31,0xAE 62 + ,0x00,0x00,0x91,0x4C,0x0F,0xE6 63 + ,0x43,0xFF,0xEC,0x31,0x5E,0x00 64 + ,0x00,0xA1,0xEB,0x31,0x08,0x00 65 + ,0x00,0xA6,0xEB,0x31,0x08,0x00 66 + ,0x00,0xAC,0x3C,0x00,0xEB,0x31 67 + ,0x08,0x00,0x00,0xA8,0x76,0xFE 68 + ,0xFE,0x08,0xEB,0x31,0x08,0x20 69 + ,0x00,0x00,0x76,0xFF,0xFF,0x18 70 + ,0xED,0x31,0x08,0x20,0x00,0x00 71 + ,0x26,0x10,0x04,0x10,0xF5,0x3C 72 + ,0x01,0x3C,0x00,0x08,0x01,0x12 73 + ,0x3C,0x11,0x3C,0x00,0x08,0x01 74 + ,0x0B,0x08,0x00,0x6D,0xEC,0x31 75 + ,0xAE,0x20,0x00,0x06,0xED,0x4D 76 + ,0x08,0x00,0x00,0x67,0x80,0x6F 77 + ,0x00,0x01,0x0B,0x6F,0x00,0x02 78 + ,0x2E,0x76,0xEE,0x01,0x48,0x06 79 + ,0x01,0x39,0xED,0x4D,0x18,0x00 80 + ,0x02,0xED,0x4D,0x08,0x00,0x04 81 + ,0x14,0x06,0xA4,0xED,0x31,0x22 82 + ,0x00,0x00,0xAC,0x76,0xEE,0x07 83 + ,0x48,0x6D,0x22,0x01,0x1E,0x08 84 + ,0x01,0x58,0xEB,0x31,0x08,0x00 85 + ,0x00,0xAC,0x06,0xFF,0xBA,0x3C 86 + ,0x00,0xEB,0x31,0x08,0x20,0x00 87 + ,0x04,0x3C,0x30,0xEB,0x31,0x08 88 + ,0x20,0x00,0x02,0x3C,0x10,0xEB 89 + ,0x31,0x08,0x20,0x00,0x00,0xED 90 + ,0x31,0x08,0x20,0x00,0x00,0x04 91 + ,0x10,0xF7,0xED,0x31,0x08,0x00 92 + ,0x00,0xA2,0x91,0x00,0x9C,0x3C 93 + ,0x80,0xEB,0x31,0x08,0x20,0x00 94 + ,0x04,0x3C,0x20,0xEB,0x31,0x08 95 + ,0x20,0x00,0x02,0x3C,0x10,0xEB 96 + ,0x31,0x08,0x20,0x00,0x00,0xED 97 + ,0x31,0x08,0x20,0x00,0x00,0x04 98 + ,0x10,0xF7,0xED,0x31,0x08,0x20 99 + ,0x00,0x04,0x42,0x10,0x90,0x08 100 + ,0xEC,0x31,0xAE,0x20,0x00,0x06 101 + ,0xA4,0x41,0x08,0x00,0xB6,0xED 102 + ,0x41,0x28,0x7D,0xFF,0xFF,0x22 103 + ,0xB3,0x40,0x98,0x2A,0x32,0xEB 104 + ,0x41,0x28,0xB4,0x43,0xFC,0x05 105 + ,0xFF,0xE6,0xA0,0x31,0x20,0x00 106 + ,0x06,0xEB,0x31,0x08,0x20,0x00 107 + ,0x04,0x3C,0x20,0xEB,0x31,0x08 108 + ,0x20,0x00,0x02,0x3C,0x10,0xEB 109 + ,0x31,0x08,0x20,0x00,0x00,0xED 110 + ,0x31,0x08,0x20,0x00,0x00,0x04 111 + ,0x10,0xF7,0xED,0x31,0x08,0x20 112 + ,0x00,0x04,0x42,0x10,0x90,0x08 113 + ,0xEC,0x31,0xAE,0x20,0x00,0x06 114 + ,0xA4,0x41,0x08,0x00,0x68,0xED 115 + ,0x41,0x28,0x7D,0xFF,0xFF,0x22 116 + ,0xB3,0x40,0x98,0x2A,0x32,0xEB 117 + ,0x41,0x28,0xB4,0x43,0xFC,0x05 118 + ,0xFF,0xE6,0x48,0x04,0xEB,0x31 119 + ,0x08,0x20,0x00,0x04,0xEB,0x31 120 + ,0x18,0x20,0x00,0x02,0x3C,0x11 121 + ,0xEB,0x31,0x18,0x20,0x00,0x00 122 + ,0xED,0x31,0x08,0x20,0x00,0x00 123 + ,0x04,0x10,0xF7,0xED,0x31,0x08 124 + ,0x20,0x00,0x02,0x66,0x00,0x6F 125 + ,0x00,0x01,0x16,0x76,0xEE,0x06 126 + ,0x48,0x4A,0x1E,0x48,0x04,0xED 127 + ,0x31,0x08,0x20,0x00,0x04,0xEB 128 + ,0x31,0x08,0x00,0x00,0xA4,0x48 129 + ,0x04,0xED,0x31,0x08,0x20,0x00 130 + ,0x04,0xEB,0x31,0x08,0x00,0x00 131 + ,0xA2,0x48,0x04,0x20,0x20,0x4A 132 + ,0x7C,0x46,0x82,0x50,0x05,0x50 133 + ,0x15,0xB5,0x1E,0x98,0xED,0x31 134 + ,0x08,0x00,0x00,0xA8,0x10,0x47 135 + ,0x3B,0x2C,0x01,0xDB,0x40,0x11 136 + ,0x98,0xC1,0x1E,0x98,0x10,0x07 137 + ,0x30,0xF9,0x40,0x07,0x18,0x98 138 + ,0x2A,0x10,0xEB,0x31,0x08,0x00 139 + ,0x00,0xA8,0xA4,0x1E,0x98,0xBB 140 + ,0x1E,0x98,0x50,0x14,0x50,0x04 141 + ,0x46,0x83,0x48,0x04,0x02,0x01 142 + ,0x00,0x50,0x05,0x50,0x15,0x10 143 + ,0x87,0x3F,0x90,0x2B,0x18,0x01 144 + ,0x00,0xC0,0x31,0x00,0x00,0xAE 145 + ,0xDF,0x41,0x00,0x08,0x00,0x1A 146 + ,0x42,0x11,0x67,0x01,0xDF,0x41 147 + ,0x02,0x08,0x00,0x10,0x42,0x11 148 + ,0x62,0x01,0xB4,0x43,0x4A,0x68 149 + ,0x50,0x14,0x50,0x04,0x24,0x10 150 + ,0x48,0x04,0xF2,0x31,0x00,0x01 151 + ,0x00,0x00,0xAE,0xF6,0x31,0x00 152 + ,0x01,0x00,0x00,0xAE,0x62,0xE4 153 + ,0xE5,0x61,0x04,0x48,0x04,0xE5 154 + ,0x63,0x05,0x48,0x04,0x20,0x20 155 + ,0x00,0x00,0x00,0x00 156 + }; 157 + 158 + #endif
+14
drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
··· 1 + device "ft1000_cs" 2 + class "network" module "ft1000","ft1000_cs" 3 + 4 + card "flarion FT1000" 5 + manfid 0x02cc, 0x0100 6 + bind "ft1000_cs" 7 + 8 + card "flarion FT1000" 9 + manfid 0x02cc, 0x1000 10 + bind "ft1000_cs" 11 + 12 + card "flarion FT1000" 13 + manfid 0x02cc, 0x1300 14 + bind "ft1000_cs"
+409
drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
··· 1 + //--------------------------------------------------------------------------- 2 + // FT1000 driver for Flarion Flash OFDM NIC Device 3 + // 4 + // Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + // 6 + // This program is free software; you can redistribute it and/or modify it 7 + // under the terms of the GNU General Public License as published by the Free 8 + // Software Foundation; either version 2 of the License, or (at your option) any 9 + // later version. This program is distributed in the hope that it will be useful, 10 + // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + // more details. You should have received a copy of the GNU General Public 13 + // License along with this program; if not, write to the 14 + // Free Software Foundation, Inc., 59 Temple Place - 15 + // Suite 330, Boston, MA 02111-1307, USA. 16 + //--------------------------------------------------------------------------- 17 + // 18 + // File: ft1000.h 19 + // 20 + // Description: Common structures and defines 21 + // 22 + // History: 23 + // 8/29/02 Whc Ported to Linux. 24 + // 7/19/04 Whc Drop packet and cmd msg with pseudo header 25 + // checksum 26 + // 10/27/04 Whc Added dynamic downloading of test image. 27 + // 01/11/04 Whc Added support for Magnemite ASIC 28 + // 29 + //--------------------------------------------------------------------------- 30 + #ifndef _FT1000H_ 31 + #define _FT1000H_ 32 + 33 + 34 + #define FT1000_DRV_VER 0x01010300 35 + 36 + #define DSPVERSZ 4 37 + #define HWSERNUMSZ 16 38 + #define SKUSZ 20 39 + #define EUISZ 8 40 + #define MODESZ 2 41 + #define CALVERSZ 2 42 + #define CALDATESZ 6 43 + 44 + // Pseudo Header structure 45 + typedef struct _PSEUDO_HDR 46 + { 47 + unsigned short length; // length of msg body 48 + unsigned char source; // hardware source id 49 + // Host = 0x10 50 + // Dsp = 0x20 51 + unsigned char destination; // hardware destination id (refer to source) 52 + unsigned char portdest; // software destination port id 53 + // Host = 0x00 54 + // Applicaton Broadcast = 0x10 55 + // Network Stack = 0x20 56 + // Dsp OAM = 0x80 57 + // Dsp Airlink = 0x90 58 + // Dsp Loader = 0xa0 59 + // Dsp MIP = 0xb0 60 + unsigned char portsrc; // software source port id (refer to portdest) 61 + unsigned short sh_str_id; // not used 62 + unsigned char control; // not used 63 + unsigned char rsvd1; 64 + unsigned char seq_num; // message sequence number 65 + unsigned char rsvd2; 66 + unsigned short qos_class; // not used 67 + unsigned short checksum; // pseudo header checksum 68 + } __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR; 69 + 70 + // Definitions to maintain compatibility between other platforms 71 + #define UCHAR u8 72 + #define USHORT u16 73 + #define ULONG u32 74 + #define BOOLEAN u8 75 + #define PULONG u32 * 76 + #define PUSHORT u16 * 77 + #define PUCHAR u8 * 78 + #define PCHAR u8 * 79 + #define UINT u32 80 + 81 + #define ELECTRABUZZ_ID 0 // ASIC ID for Electrabuzz 82 + #define MAGNEMITE_ID 0x1a01 // ASIC ID for Magnemite 83 + 84 + // MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE 85 + #define FT1000_REG_DPRAM_ADDR 0x000E // DPADR - Dual Port Ram Indirect Address Register 86 + #define FT1000_REG_SUP_CTRL 0x0020 // HCTR - Host Control Register 87 + #define FT1000_REG_SUP_STAT 0x0022 // HSTAT - Host Status Register 88 + #define FT1000_REG_RESET 0x0024 // HCTR - Host Control Register 89 + #define FT1000_REG_SUP_ISR 0x0026 // HISR - Host Interrupt Status Register 90 + #define FT1000_REG_SUP_IMASK 0x0028 // HIMASK - Host Interrupt Mask 91 + #define FT1000_REG_DOORBELL 0x002a // DBELL - Door Bell Register 92 + #define FT1000_REG_ASIC_ID 0x002e // ASICID - ASIC Identification Number 93 + // (Electrabuzz=0 Magnemite=0x1A01) 94 + 95 + // MEMORY MAP FOR ELECTRABUZZ ASIC 96 + 97 + #define FT1000_REG_UFIFO_STAT 0x0000 // UFSR - Uplink FIFO status register 98 + #define FT1000_REG_UFIFO_BEG 0x0002 // UFBR - Uplink FIFO beginning register 99 + #define FT1000_REG_UFIFO_MID 0x0004 // UFMR - Uplink FIFO middle register 100 + #define FT1000_REG_UFIFO_END 0x0006 // UFER - Uplink FIFO end register 101 + #define FT1000_REG_DFIFO_STAT 0x0008 // DFSR - Downlink FIFO status register 102 + #define FT1000_REG_DFIFO 0x000A // DFR - Downlink FIFO Register 103 + #define FT1000_REG_DPRAM_DATA 0x000C // DPRAM - Dual Port Indirect Data Register 104 + #define FT1000_REG_WATERMARK 0x0010 // WMARK - Watermark Register 105 + 106 + // MEMORY MAP FOR MAGNEMITE 107 + #define FT1000_REG_MAG_UFDR 0x0000 // UFDR - Uplink FIFO Data Register (32-bits) 108 + #define FT1000_REG_MAG_UFDRL 0x0000 // UFDRL - Uplink FIFO Data Register low-word (16-bits) 109 + #define FT1000_REG_MAG_UFDRH 0x0002 // UFDRH - Uplink FIFO Data Register high-word (16-bits) 110 + #define FT1000_REG_MAG_UFER 0x0004 // UFER - Uplink FIFO End Register 111 + #define FT1000_REG_MAG_UFSR 0x0006 // UFSR - Uplink FIFO Status Register 112 + #define FT1000_REG_MAG_DFR 0x0008 // DFR - Downlink FIFO Register (32-bits) 113 + #define FT1000_REG_MAG_DFRL 0x0008 // DFRL - Downlink FIFO Register low-word (16-bits) 114 + #define FT1000_REG_MAG_DFRH 0x000a // DFRH - Downlink FIFO Register high-word (16-bits) 115 + #define FT1000_REG_MAG_DFSR 0x000c // DFSR - Downlink FIFO Status Register 116 + #define FT1000_REG_MAG_DPDATA 0x0010 // DPDATA - Dual Port RAM Indirect Data Register (32-bits) 117 + #define FT1000_REG_MAG_DPDATAL 0x0010 // DPDATAL - Dual Port RAM Indirect Data Register low-word (16-bits) 118 + #define FT1000_REG_MAG_DPDATAH 0x0012 // DPDATAH - Dual Port RAM Indirect Data Register high-word (16-bits) 119 + #define FT1000_REG_MAG_WATERMARK 0x002c // WMARK - Watermark Register 120 + 121 + // Reserved Dual Port RAM offsets for Electrabuzz 122 + #define FT1000_DPRAM_TX_BASE 0x0002 // Host to PC Card Messaging Area 123 + #define FT1000_DPRAM_RX_BASE 0x0800 // PC Card to Host Messaging Area 124 + #define FT1000_FIFO_LEN 0x7FC // total length for DSP FIFO tracking 125 + #define FT1000_HI_HO 0x7FE // heartbeat with HI/HO 126 + #define FT1000_DSP_STATUS 0xFFE // dsp status - non-zero is a request to reset dsp 127 + #define FT1000_DSP_LED 0xFFA // dsp led status for PAD device 128 + #define FT1000_DSP_CON_STATE 0xFF8 // DSP Connection Status Info 129 + #define FT1000_DPRAM_FEFE 0x002 // location for dsp ready indicator 130 + #define FT1000_DSP_TIMER0 0x1FF0 // Timer Field from Basestation 131 + #define FT1000_DSP_TIMER1 0x1FF2 // Timer Field from Basestation 132 + #define FT1000_DSP_TIMER2 0x1FF4 // Timer Field from Basestation 133 + #define FT1000_DSP_TIMER3 0x1FF6 // Timer Field from Basestation 134 + 135 + // Reserved Dual Port RAM offsets for Magnemite 136 + #define FT1000_DPRAM_MAG_TX_BASE 0x0000 // Host to PC Card Messaging Area 137 + #define FT1000_DPRAM_MAG_RX_BASE 0x0200 // PC Card to Host Messaging Area 138 + #define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking 139 + #define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index 140 + #define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO 141 + #define FT1000_MAG_HI_HO_INDX 0x0 // high-word index 142 + #define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device 143 + #define FT1000_MAG_DSP_LED_INDX 0x0 // dsp led status for PAD device 144 + 145 + #define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info 146 + #define FT1000_MAG_DSP_CON_STATE_INDX 0x1 // DSP Connection Status Info 147 + 148 + #define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator 149 + #define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator 150 + 151 + #define FT1000_MAG_DSP_TIMER0 0x3FC // Timer Field from Basestation 152 + #define FT1000_MAG_DSP_TIMER0_INDX 0x1 153 + 154 + #define FT1000_MAG_DSP_TIMER1 0x3FC // Timer Field from Basestation 155 + #define FT1000_MAG_DSP_TIMER1_INDX 0x0 156 + 157 + #define FT1000_MAG_DSP_TIMER2 0x3FD // Timer Field from Basestation 158 + #define FT1000_MAG_DSP_TIMER2_INDX 0x1 159 + 160 + #define FT1000_MAG_DSP_TIMER3 0x3FD // Timer Field from Basestation 161 + #define FT1000_MAG_DSP_TIMER3_INDX 0x0 162 + 163 + #define FT1000_MAG_TOTAL_LEN 0x200 164 + #define FT1000_MAG_TOTAL_LEN_INDX 0x1 165 + 166 + #define FT1000_MAG_PH_LEN 0x200 167 + #define FT1000_MAG_PH_LEN_INDX 0x0 168 + 169 + #define FT1000_MAG_PORT_ID 0x201 170 + #define FT1000_MAG_PORT_ID_INDX 0x0 171 + 172 + #define HOST_INTF_LE 0x0 // Host interface little endian mode 173 + #define HOST_INTF_BE 0x1 // Host interface big endian mode 174 + 175 + // PC Card to Host Doorbell assignments 176 + #define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has 177 + // data for host in DPRAM 178 + #define FT1000_ASIC_RESET_REQ 0x0004 // DSP requesting host to reset the ASIC 179 + #define FT1000_DSP_ASIC_RESET 0x0008 // DSP indicating host that it will reset the ASIC 180 + #define FT1000_DB_COND_RESET 0x0010 // DSP request for a card reset. 181 + 182 + // Host to PC Card Doorbell assignments 183 + #define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has 184 + // data for DSP in DPRAM. 185 + #define FT1000_ASIC_RESET_DSP 0x0400 // Responds to FT1000_ASIC_RESET_REQ 186 + #define FT1000_DB_HB 0x1000 // Indicates that supervisor 187 + // has a heartbeat message for DSP. 188 + 189 + #define FT1000_DPRAM_BASE 0x0000 // Dual Port RAM starting offset 190 + 191 + #define hi 0x6869 // PC Card heartbeat values 192 + #define ho 0x686f // PC Card heartbeat values 193 + 194 + // Magnemite specific defines 195 + #define hi_mag 0x6968 // Byte swap hi to avoid additional system call 196 + #define ho_mag 0x6f68 // Byte swap ho to avoid additional system call 197 + 198 + // 199 + // Bit field definitions for Host Interrupt Status Register 200 + // 201 + // Indicate the cause of an interrupt. 202 + // 203 + #define ISR_EMPTY 0x00 // no bits set 204 + #define ISR_DOORBELL_ACK 0x01 // Doorbell acknowledge from DSP 205 + #define ISR_DOORBELL_PEND 0x02 // Doorbell pending from DSP 206 + #define ISR_RCV 0x04 // Packet available in Downlink FIFO 207 + #define ISR_WATERMARK 0x08 // Watermark requirements satisfied 208 + 209 + // Bit field definition for Host Interrupt Mask 210 + #define ISR_MASK_NONE 0x0000 // no bits set 211 + #define ISR_MASK_DOORBELL_ACK 0x0001 // Doorbell acknowledge mask 212 + #define ISR_MASK_DOORBELL_PEND 0x0002 // Doorbell pending mask 213 + #define ISR_MASK_RCV 0x0004 // Downlink Packet available mask 214 + #define ISR_MASK_WATERMARK 0x0008 // Watermark interrupt mask 215 + #define ISR_MASK_ALL 0xffff // Mask all interrupts 216 + 217 + // Bit field definition for Host Control Register 218 + #define DSP_RESET_BIT 0x0001 // Bit field to control dsp reset state 219 + // (0 = out of reset 1 = reset) 220 + #define ASIC_RESET_BIT 0x0002 // Bit field to control ASIC reset state 221 + // (0 = out of reset 1 = reset) 222 + 223 + // Default interrupt mask (Enable Doorbell pending and Packet available interrupts) 224 + #define ISR_DEFAULT_MASK 0x7ff9 225 + 226 + // Application specific IDs 227 + #define DSPID 0x20 228 + #define HOSTID 0x10 229 + #define DSPAIRID 0x90 230 + #define DRIVERID 0x00 231 + #define NETWORKID 0x20 232 + 233 + // Size of DPRAM Message 234 + #define MAX_CMD_SQSIZE 1780 235 + 236 + #define ENET_MAX_SIZE 1514 237 + #define ENET_HEADER_SIZE 14 238 + 239 + #define SLOWQ_TYPE 0 240 + #define FASTQ_TYPE 1 241 + 242 + #define MAX_DSP_SESS_REC 1024 243 + 244 + #define DSP_QID_OFFSET 4 245 + #define PSEUDOSZ 16 246 + #define PSEUDOSZWRD 8 247 + 248 + // Maximum number of occurrence of pseudo header errors before resetting PC Card. 249 + #define MAX_PH_ERR 300 250 + 251 + // Driver message types 252 + #define MEDIA_STATE 0x0010 253 + #define TIME_UPDATE 0x0020 254 + #define DSP_PROVISION 0x0030 255 + #define DSP_INIT_MSG 0x0050 256 + #define DSP_HIBERNATE 0x0060 257 + 258 + #define DSP_STORE_INFO 0x0070 259 + #define DSP_GET_INFO 0x0071 260 + #define GET_DRV_ERR_RPT_MSG 0x0073 261 + #define RSP_DRV_ERR_RPT_MSG 0x0074 262 + 263 + // Driver Error Messages for DSP 264 + #define DSP_HB_INFO 0x7ef0 265 + #define DSP_FIFO_INFO 0x7ef1 266 + #define DSP_CONDRESET_INFO 0x7ef2 267 + #define DSP_CMDLEN_INFO 0x7ef3 268 + #define DSP_CMDPHCKSUM_INFO 0x7ef4 269 + #define DSP_PKTPHCKSUM_INFO 0x7ef5 270 + #define DSP_PKTLEN_INFO 0x7ef6 271 + #define DSP_USER_RESET 0x7ef7 272 + #define FIFO_FLUSH_MAXLIMIT 0x7ef8 273 + #define FIFO_FLUSH_BADCNT 0x7ef9 274 + #define FIFO_ZERO_LEN 0x7efa 275 + 276 + #define HOST_QID_OFFSET 5 277 + #define QTYPE_OFFSET 13 278 + 279 + #define SUCCESS 0x00 280 + #define FAILURE 0x01 281 + #define TRUE 0x1 282 + #define FALSE 0x0 283 + 284 + #define MAX_NUM_APP 6 285 + 286 + #define MAXIMUM_ASIC_HB_CNT 15 287 + 288 + typedef struct _DRVMSG { 289 + PSEUDO_HDR pseudo; 290 + u16 type; 291 + u16 length; 292 + u8 data[0]; 293 + } __attribute__ ((packed)) DRVMSG, *PDRVMSG; 294 + 295 + typedef struct _MEDIAMSG { 296 + PSEUDO_HDR pseudo; 297 + u16 type; 298 + u16 length; 299 + u16 state; 300 + u32 ip_addr; 301 + u32 net_mask; 302 + u32 gateway; 303 + u32 dns_1; 304 + u32 dns_2; 305 + } __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG; 306 + 307 + typedef struct _TIMEMSG { 308 + PSEUDO_HDR pseudo; 309 + u16 type; 310 + u16 length; 311 + u8 timeval[8]; 312 + } __attribute__ ((packed)) TIMEMSG, *PTIMEMSG; 313 + 314 + typedef struct _DSPINITMSG { 315 + PSEUDO_HDR pseudo; 316 + u16 type; 317 + u16 length; 318 + u8 DspVer[DSPVERSZ]; // DSP version number 319 + u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number 320 + u8 Sku[SKUSZ]; // SKU 321 + u8 eui64[EUISZ]; // EUI64 322 + u8 ProductMode[MODESZ]; // Product Mode (Market/Production) 323 + u8 RfCalVer[CALVERSZ]; // Rf Calibration version 324 + u8 RfCalDate[CALDATESZ]; // Rf Calibration date 325 + } __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG; 326 + 327 + typedef struct _DSPHIBERNATE { 328 + PSEUDO_HDR pseudo; 329 + u16 type; 330 + u16 length; 331 + u32 timeout; 332 + u16 sess_info[0]; 333 + } DSPHIBERNATE, *PDSPHIBERNATE; 334 + 335 + typedef struct _APP_INFO_BLOCK 336 + { 337 + u32 fileobject; // Application's file object 338 + u16 app_id; // Application id 339 + } APP_INFO_BLOCK, *PAPP_INFO_BLOCK; 340 + 341 + typedef struct _PROV_RECORD { 342 + struct list_head list; 343 + u8 *pprov_data; 344 + } PROV_RECORD, *PPROV_RECORD; 345 + 346 + typedef struct _FT1000_INFO { 347 + struct net_device_stats stats; 348 + u16 DrvErrNum; 349 + u16 AsicID; 350 + int ASICResetNum; 351 + int DspAsicReset; 352 + int PktIntfErr; 353 + int DSPResetNum; 354 + int NumIOCTLBufs; 355 + int IOCTLBufLvl; 356 + int DeviceCreated; 357 + int CardReady; 358 + int DspHibernateFlag; 359 + int DSPReady; 360 + u8 DeviceName[15]; 361 + int DeviceMajor; 362 + int registered; 363 + int mediastate; 364 + u16 packetseqnum; 365 + u8 squeseqnum; // sequence number on slow queue 366 + spinlock_t dpram_lock; 367 + u16 CurrentInterruptEnableMask; 368 + int InterruptsEnabled; 369 + u16 fifo_cnt; 370 + u8 DspVer[DSPVERSZ]; // DSP version number 371 + u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number 372 + u8 Sku[SKUSZ]; // SKU 373 + u8 eui64[EUISZ]; // EUI64 374 + time_t ConTm; // Connection Time 375 + u16 LedStat; 376 + u16 ConStat; 377 + u16 ProgConStat; 378 + u8 ProductMode[MODESZ]; 379 + u8 RfCalVer[CALVERSZ]; 380 + u8 RfCalDate[CALDATESZ]; 381 + u16 DSP_TIME[4]; 382 + struct list_head prov_list; 383 + int appcnt; 384 + APP_INFO_BLOCK app_info[MAX_NUM_APP]; 385 + u16 DSPInfoBlklen; 386 + u16 DrvMsgPend; 387 + int (*ft1000_reset)(void *); 388 + void *link; 389 + u16 DSPInfoBlk[MAX_DSP_SESS_REC]; 390 + union { 391 + u16 Rec[MAX_DSP_SESS_REC]; 392 + u32 MagRec[MAX_DSP_SESS_REC/2]; 393 + } DSPSess; 394 + struct proc_dir_entry *proc_ft1000; 395 + char netdevname[IFNAMSIZ]; 396 + } FT1000_INFO, *PFT1000_INFO; 397 + 398 + typedef struct _DPRAM_BLK { 399 + struct list_head list; 400 + u16 *pbuffer; 401 + } __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK; 402 + 403 + extern u16 ft1000_read_dpram (struct net_device *dev, int offset); 404 + extern void card_bootload(struct net_device *dev); 405 + extern u16 ft1000_read_dpram_mag_16 (struct net_device *dev, int offset, int Index); 406 + extern u32 ft1000_read_dpram_mag_32 (struct net_device *dev, int offset); 407 + void ft1000_write_dpram_mag_32 (struct net_device *dev, int offset, u32 value); 408 + 409 + #endif // _FT1000H_
drivers/staging/ft1000/ft1000-pcmcia/ft1000.img

This is a binary file and will not be displayed.

+513
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
··· 1 + /*--------------------------------------------------------------------------- 2 + FT1000 driver for Flarion Flash OFDM NIC Device 3 + 4 + Copyright (C) 1999 David A. Hinds. All Rights Reserved. 5 + Copyright (C) 2002 Flarion Technologies, All rights reserved. 6 + Copyright (C) 2006 Patrik Ostrihon, All rights reserved. 7 + Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved. 8 + 9 + The initial developer of the original code is David A. Hinds 10 + <dahinds@users.sourceforge.net>. Portions created by David A. Hinds. 11 + 12 + This file was modified to support the Flarion Flash OFDM NIC Device 13 + by Wai Chan (w.chan@flarion.com). 14 + 15 + Port for kernel 2.6 created by Patrik Ostrihon (patrik.ostrihon@pwc.sk) 16 + 17 + This program is free software; you can redistribute it and/or modify it 18 + under the terms of the GNU General Public License as published by the Free 19 + Software Foundation; either version 2 of the License, or (at your option) any 20 + later version. This program is distributed in the hope that it will be useful, 21 + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 22 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 23 + more details. You should have received a copy of the GNU General Public 24 + License along with this program; if not, write to the 25 + Free Software Foundation, Inc., 59 Temple Place - 26 + Suite 330, Boston, MA 02111-1307, USA. 27 + -----------------------------------------------------------------------------*/ 28 + 29 + #include <linux/kernel.h> 30 + #include <linux/module.h> 31 + #include <linux/init.h> 32 + #include <linux/ptrace.h> 33 + #include <linux/slab.h> 34 + #include <linux/string.h> 35 + #include <linux/timer.h> 36 + #include <linux/ioport.h> 37 + #include <linux/delay.h> 38 + 39 + #include <linux/netdevice.h> 40 + #include <linux/etherdevice.h> 41 + 42 + //#include <pcmcia/version.h> // Slavius 21.10.2009 removed from kernel 43 + #include <pcmcia/cs_types.h> 44 + #include <pcmcia/cs.h> 45 + #include <pcmcia/cistpl.h> 46 + #include <pcmcia/cisreg.h> 47 + #include <pcmcia/ds.h> 48 + 49 + #include <asm/io.h> 50 + #include <asm/system.h> 51 + #include <asm/byteorder.h> 52 + #include <asm/uaccess.h> 53 + 54 + #include "ft1000_cs.h" // Slavius 21.10.2009 because CS_SUCCESS constant is missing due to removed pcmcia/version.h 55 + 56 + /*====================================================================*/ 57 + 58 + /* Module parameters */ 59 + 60 + #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") 61 + 62 + MODULE_AUTHOR("Wai Chan"); 63 + MODULE_DESCRIPTION("FT1000 PCMCIA driver"); 64 + MODULE_LICENSE("GPL"); 65 + 66 + /* Newer, simpler way of listing specific interrupts */ 67 + 68 + /* The old way: bit map of interrupts to choose from */ 69 + /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ 70 + 71 + /* 72 + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If 73 + you do not define PCMCIA_DEBUG at all, all the debug code will be 74 + left out. If you compile with PCMCIA_DEBUG=0, the debug code will 75 + be present but disabled. 76 + */ 77 + #ifdef FT_DEBUG 78 + #define DEBUG(n, args...) printk(KERN_DEBUG args) 79 + #else 80 + #define DEBUG(n, args...) 81 + #endif 82 + 83 + /*====================================================================*/ 84 + 85 + struct net_device *init_ft1000_card(int, int, unsigned char *, 86 + void *ft1000_reset, struct pcmcia_device * link, 87 + struct device *fdev); 88 + void stop_ft1000_card(struct net_device *); 89 + 90 + static int ft1000_config(struct pcmcia_device *link); 91 + static void ft1000_release(struct pcmcia_device *link); 92 + 93 + /* 94 + The attach() and detach() entry points are used to create and destroy 95 + "instances" of the driver, where each instance represents everything 96 + needed to manage one actual PCMCIA card. 97 + */ 98 + 99 + static void ft1000_detach(struct pcmcia_device *link); 100 + static int ft1000_attach(struct pcmcia_device *link); 101 + 102 + typedef struct local_info_t { 103 + struct pcmcia_device *link; 104 + struct net_device *dev; 105 + } local_info_t; 106 + 107 + #define MAX_ASIC_RESET_CNT 10 108 + #define COR_DEFAULT 0x55 109 + 110 + /*====================================================================*/ 111 + 112 + static void ft1000_reset(struct pcmcia_device * link) 113 + { 114 + conf_reg_t reg; 115 + 116 + DEBUG(0, "ft1000_cs:ft1000_reset is called................\n"); 117 + 118 + /* Soft-Reset card */ 119 + reg.Action = CS_WRITE; 120 + reg.Offset = CISREG_COR; 121 + reg.Value = COR_SOFT_RESET; 122 + pcmcia_access_configuration_register(link, &reg); 123 + 124 + /* Wait until the card has acknowledged our reset */ 125 + udelay(2); 126 + 127 + /* Restore original COR configuration index */ 128 + /* Need at least 2 write to respond */ 129 + reg.Action = CS_WRITE; 130 + reg.Offset = CISREG_COR; 131 + reg.Value = COR_DEFAULT; 132 + pcmcia_access_configuration_register(link, &reg); 133 + 134 + /* Wait until the card has finished restarting */ 135 + udelay(1); 136 + 137 + reg.Action = CS_WRITE; 138 + reg.Offset = CISREG_COR; 139 + reg.Value = COR_DEFAULT; 140 + pcmcia_access_configuration_register(link, &reg); 141 + 142 + /* Wait until the card has finished restarting */ 143 + udelay(1); 144 + 145 + reg.Action = CS_WRITE; 146 + reg.Offset = CISREG_COR; 147 + reg.Value = COR_DEFAULT; 148 + pcmcia_access_configuration_register(link, &reg); 149 + 150 + /* Wait until the card has finished restarting */ 151 + udelay(1); 152 + 153 + } 154 + 155 + /*====================================================================*/ 156 + 157 + static int get_tuple_first(struct pcmcia_device *link, tuple_t * tuple, 158 + cisparse_t * parse) 159 + { 160 + int i; 161 + i = pcmcia_get_first_tuple(link, tuple); 162 + if (i != CS_SUCCESS) 163 + return i; 164 + i = pcmcia_get_tuple_data(link, tuple); 165 + if (i != CS_SUCCESS) 166 + return i; 167 + return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter 168 + } 169 + 170 + static int get_tuple_next(struct pcmcia_device *link, tuple_t * tuple, 171 + cisparse_t * parse) 172 + { 173 + int i; 174 + i = pcmcia_get_next_tuple(link, tuple); 175 + if (i != CS_SUCCESS) 176 + return i; 177 + i = pcmcia_get_tuple_data(link, tuple); 178 + if (i != CS_SUCCESS) 179 + return i; 180 + return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter 181 + } 182 + 183 + /*====================================================================== 184 + 185 + 186 + ======================================================================*/ 187 + 188 + static int ft1000_attach(struct pcmcia_device *link) 189 + { 190 + 191 + local_info_t *local; 192 + 193 + DEBUG(0, "ft1000_cs: ft1000_attach()\n"); 194 + 195 + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); 196 + if (!local) { 197 + return -ENOMEM; 198 + } 199 + memset(local, 0, sizeof(local_info_t)); 200 + local->link = link; 201 + 202 + link->priv = local; 203 + local->dev = NULL; 204 + 205 + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 206 + link->irq.IRQInfo1 = IRQ_LEVEL_ID; 207 + link->conf.Attributes = CONF_ENABLE_IRQ; 208 + link->conf.IntType = INT_MEMORY_AND_IO; 209 + link->irq.Handler = NULL; 210 + 211 + return ft1000_config(link); 212 + } /* ft1000_attach */ 213 + 214 + /*====================================================================== 215 + 216 + This deletes a driver "instance". The device is de-registered 217 + with Card Services. If it has been released, all local data 218 + structures are freed. Otherwise, the structures will be freed 219 + when the device is released. 220 + 221 + ======================================================================*/ 222 + 223 + static void ft1000_detach(struct pcmcia_device *link) 224 + { 225 + struct net_device *dev = ((local_info_t *) link->priv)->dev; 226 + 227 + DEBUG(0, "ft1000_cs: ft1000_detach(0x%p)\n", link); 228 + 229 + if (link == NULL) { 230 + DEBUG(0,"ft1000_cs:ft1000_detach: Got a NULL pointer\n"); 231 + return; 232 + } 233 + 234 + if (dev) { 235 + stop_ft1000_card(dev); 236 + } 237 + 238 + ft1000_release(link); 239 + 240 + /* This points to the parent local_info_t struct */ 241 + free_netdev(dev); 242 + 243 + } /* ft1000_detach */ 244 + 245 + /*====================================================================== 246 + 247 + ft1000_config() is scheduled to run after a CARD_INSERTION event 248 + is received, to configure the PCMCIA socket, and to make the 249 + device available to the system. 250 + 251 + ======================================================================*/ 252 + 253 + #define CS_CHECK(fn, ret) \ 254 + do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 255 + 256 + #define CFG_CHECK(fn, ret) \ 257 + last_fn = (fn); if ((last_ret = (ret)) != 0) goto next_entry 258 + 259 + static int ft1000_config(struct pcmcia_device * link) 260 + { 261 + tuple_t tuple; 262 + cisparse_t parse; 263 + int last_fn, last_ret, i; 264 + u_char buf[64]; 265 + cistpl_lan_node_id_t *node_id; 266 + cistpl_cftable_entry_t dflt = { 0 }; 267 + cistpl_cftable_entry_t *cfg; 268 + unsigned char mac_address[6]; 269 + 270 + DEBUG(0, "ft1000_cs: ft1000_config(0x%p)\n", link); 271 + 272 + /* 273 + This reads the card's CONFIG tuple to find its configuration 274 + registers. 275 + */ 276 + // tuple.DesiredTuple = CISTPL_CONFIG; 277 + // tuple.Attributes = 0; 278 + tuple.TupleData = buf; 279 + tuple.TupleDataMax = sizeof(buf); 280 + tuple.TupleOffset = 0; 281 + // CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 282 + // CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); 283 + // CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); 284 + // link->conf.ConfigBase = parse.config.base; 285 + // link->conf.Present = parse.config.rmask[0]; 286 + 287 + /* 288 + In this loop, we scan the CIS for configuration table entries, 289 + each of which describes a valid card configuration, including 290 + voltage, IO window, memory window, and interrupt settings. 291 + 292 + We make no assumptions about the card to be configured: we use 293 + just the information available in the CIS. In an ideal world, 294 + this would work for any PCMCIA card, but it requires a complete 295 + and accurate CIS. In practice, a driver usually "knows" most of 296 + these things without consulting the CIS, and most client drivers 297 + will only use the CIS to fill in implementation-defined details. 298 + */ 299 + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 300 + tuple.Attributes = 0; 301 + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 302 + while (1) { 303 + cfg = &(parse.cftable_entry); 304 + CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); 305 + CFG_CHECK(ParseTuple, 306 + pcmcia_parse_tuple(&tuple, &parse)); // Slavius 21.10.2009 removed unused link parameter 307 + 308 + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 309 + dflt = *cfg; 310 + if (cfg->index == 0) 311 + goto next_entry; 312 + link->conf.ConfigIndex = cfg->index; 313 + 314 + /* Do we need to allocate an interrupt? */ 315 + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 316 + link->conf.Attributes |= CONF_ENABLE_IRQ; 317 + 318 + /* IO window settings */ 319 + link->io.NumPorts1 = link->io.NumPorts2 = 0; 320 + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 321 + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 322 + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 323 + if (!(io->flags & CISTPL_IO_8BIT)) { 324 + DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_16\n"); 325 + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 326 + } 327 + if (!(io->flags & CISTPL_IO_16BIT)) { 328 + DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_8\n"); 329 + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 330 + } 331 + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 332 + link->io.BasePort1 = io->win[0].base; 333 + link->io.NumPorts1 = io->win[0].len; 334 + if (io->nwin > 1) { 335 + link->io.Attributes2 = link->io.Attributes1; 336 + link->io.BasePort2 = io->win[1].base; 337 + link->io.NumPorts2 = io->win[1].len; 338 + } 339 + /* This reserves IO space but doesn't actually enable it */ 340 + pcmcia_request_io(link, &link->io); 341 + } 342 + 343 + break; 344 + 345 + next_entry: 346 + last_ret = pcmcia_get_next_tuple(link, &tuple); 347 + } 348 + if (last_ret != CS_SUCCESS) { 349 + cs_error(link, RequestIO, last_ret); 350 + goto failed; 351 + } 352 + 353 + /* 354 + Allocate an interrupt line. Note that this does not assign a 355 + handler to the interrupt, unless the 'Handler' member of the 356 + irq structure is initialized. 357 + */ 358 + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); 359 + 360 + /* 361 + This actually configures the PCMCIA socket -- setting up 362 + the I/O windows and the interrupt mapping, and putting the 363 + card and host interface into "Memory and IO" mode. 364 + */ 365 + CS_CHECK(RequestConfiguration, 366 + pcmcia_request_configuration(link, &link->conf)); 367 + 368 + /* Get MAC address from tuples */ 369 + 370 + tuple.Attributes = tuple.TupleOffset = 0; 371 + tuple.TupleData = buf; 372 + tuple.TupleDataMax = sizeof(buf); 373 + 374 + /* Check for a LAN function extension tuple */ 375 + tuple.DesiredTuple = CISTPL_FUNCE; 376 + i = get_tuple_first(link, &tuple, &parse); 377 + while (i == CS_SUCCESS) { 378 + if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID) 379 + break; 380 + i = get_tuple_next(link, &tuple, &parse); 381 + } 382 + 383 + if (i == CS_SUCCESS) { 384 + node_id = (cistpl_lan_node_id_t *) parse.funce.data; 385 + if (node_id->nb == 6) { 386 + for (i = 0; i < 6; i++) 387 + mac_address[i] = node_id->id[i]; 388 + } 389 + } 390 + 391 + ((local_info_t *) link->priv)->dev = 392 + init_ft1000_card(link->irq.AssignedIRQ, link->io.BasePort1, 393 + &mac_address[0], ft1000_reset, link, 394 + &handle_to_dev(link)); 395 + 396 + /* 397 + At this point, the dev_node_t structure(s) need to be 398 + initialized and arranged in a linked list at link->dev. 399 + */ 400 + 401 + /* Finally, report what we've done */ 402 + 403 + return 0; 404 + 405 + cs_failed: 406 + cs_error(link, last_fn, last_ret); 407 + failed: 408 + ft1000_release(link); 409 + return -ENODEV; 410 + 411 + } /* ft1000_config */ 412 + 413 + /*====================================================================== 414 + 415 + After a card is removed, ft1000_release() will unregister the 416 + device, and release the PCMCIA configuration. If the device is 417 + still open, this will be postponed until it is closed. 418 + 419 + ======================================================================*/ 420 + 421 + static void ft1000_release(struct pcmcia_device * link) 422 + { 423 + 424 + DEBUG(0, "ft1000_cs: ft1000_release(0x%p)\n", link); 425 + 426 + /* 427 + If the device is currently in use, we won't release until it 428 + is actually closed, because until then, we can't be sure that 429 + no one will try to access the device or its data structures. 430 + */ 431 + 432 + /* Unlink the device chain */ 433 + link->dev_node = NULL; 434 + 435 + /* 436 + In a normal driver, additional code may be needed to release 437 + other kernel data structures associated with this device. 438 + */ 439 + 440 + /* Don't bother checking to see if these succeed or not */ 441 + 442 + pcmcia_disable_device(link); 443 + } /* ft1000_release */ 444 + 445 + /*====================================================================== 446 + 447 + The card status event handler. Mostly, this schedules other 448 + stuff to run after an event is received. 449 + 450 + When a CARD_REMOVAL event is received, we immediately set a 451 + private flag to block future accesses to this device. All the 452 + functions that actually access the device should check this flag 453 + to make sure the card is still present. 454 + 455 + ======================================================================*/ 456 + 457 + static int ft1000_suspend(struct pcmcia_device *link) 458 + { 459 + struct net_device *dev = ((local_info_t *) link->priv)->dev; 460 + 461 + DEBUG(1, "ft1000_cs: ft1000_event(0x%06x)\n", event); 462 + 463 + if (link->open) 464 + netif_device_detach(dev); 465 + return 0; 466 + } 467 + 468 + static int ft1000_resume(struct pcmcia_device *link) 469 + { 470 + /* struct net_device *dev = link->priv; 471 + */ 472 + return 0; 473 + } 474 + 475 + 476 + 477 + /*====================================================================*/ 478 + 479 + static struct pcmcia_device_id ft1000_ids[] = { 480 + PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x0100), 481 + PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1000), 482 + PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1300), 483 + PCMCIA_DEVICE_NULL, 484 + }; 485 + 486 + MODULE_DEVICE_TABLE(pcmcia, ft1000_ids); 487 + 488 + static struct pcmcia_driver ft1000_cs_driver = { 489 + .owner = THIS_MODULE, 490 + .drv = { 491 + .name = "ft1000_cs", 492 + }, 493 + .probe = ft1000_attach, 494 + .remove = ft1000_detach, 495 + .id_table = ft1000_ids, 496 + .suspend = ft1000_suspend, 497 + .resume = ft1000_resume, 498 + }; 499 + 500 + static int __init init_ft1000_cs(void) 501 + { 502 + DEBUG(0, "ft1000_cs: loading\n"); 503 + return pcmcia_register_driver(&ft1000_cs_driver); 504 + } 505 + 506 + static void __exit exit_ft1000_cs(void) 507 + { 508 + DEBUG(0, "ft1000_cs: unloading\n"); 509 + pcmcia_unregister_driver(&ft1000_cs_driver); 510 + } 511 + 512 + module_init(init_ft1000_cs); 513 + module_exit(exit_ft1000_cs);
+1
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h
··· 1 + #define CS_SUCCESS 0x00
+66
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
··· 1 + //--------------------------------------------------------------------------- 2 + // FT1000 driver for Flarion Flash OFDM NIC Device 3 + // 4 + // Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + // 6 + // This program is free software; you can redistribute it and/or modify it 7 + // under the terms of the GNU General Public License as published by the Free 8 + // Software Foundation; either version 2 of the License, or (at your option) any 9 + // later version. This program is distributed in the hope that it will be useful, 10 + // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + // more details. You should have received a copy of the GNU General Public 13 + // License along with this program; if not, write to the 14 + // Free Software Foundation, Inc., 59 Temple Place - 15 + // Suite 330, Boston, MA 02111-1307, USA. 16 + //--------------------------------------------------------------------------- 17 + // 18 + // File: ft1000_dev.h 19 + // 20 + // Description: Register definitions and bit masks for the FT1000 NIC 21 + // 22 + // History: 23 + // 2/5/02 Ivan Bohannon Written. 24 + // 8/29/02 Whc Ported to Linux. 25 + // 26 + //--------------------------------------------------------------------------- 27 + #ifndef _FT1000_DEVH_ 28 + #define _FT1000_DEVH_ 29 + 30 + //--------------------------------------------------------------------------- 31 + // 32 + // Function: ft1000_read_reg 33 + // Descripton: This function will read the value of a given ASIC register. 34 + // Input: 35 + // dev - device structure 36 + // offset - ASIC register offset 37 + // Output: 38 + // data - ASIC register value 39 + // 40 + //--------------------------------------------------------------------------- 41 + static inline u16 ft1000_read_reg (struct net_device *dev, u16 offset) { 42 + u16 data = 0; 43 + 44 + data = inw(dev->base_addr + offset); 45 + 46 + return (data); 47 + } 48 + 49 + //--------------------------------------------------------------------------- 50 + // 51 + // Function: ft1000_write_reg 52 + // Descripton: This function will set the value for a given ASIC register. 53 + // Input: 54 + // dev - device structure 55 + // offset - ASIC register offset 56 + // value - value to write 57 + // Output: 58 + // None. 59 + // 60 + //--------------------------------------------------------------------------- 61 + static inline void ft1000_write_reg (struct net_device *dev, u16 offset, u16 value) { 62 + outw (value, dev->base_addr + offset); 63 + } 64 + 65 + #endif // _FT1000_DEVH_ 66 +
+940
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
··· 1 + /*--------------------------------------------------------------------------- 2 + FT1000 driver for Flarion Flash OFDM NIC Device 3 + 4 + Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + 6 + This program is free software; you can redistribute it and/or modify it 7 + under the terms of the GNU General Public License as published by the Free 8 + Software Foundation; either version 2 of the License, or (at your option) any 9 + later version. This program is distributed in the hope that it will be useful, 10 + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + more details. You should have received a copy of the GNU General Public 13 + License along with this program; if not, write to the 14 + Free Software Foundation, Inc., 59 Temple Place - 15 + Suite 330, Boston, MA 02111-1307, USA. 16 + -------------------------------------------------------------------------- 17 + 18 + Description: This module will handshake with the DSP bootloader to 19 + download the DSP runtime image. 20 + 21 + ---------------------------------------------------------------------------*/ 22 + 23 + #define __KERNEL_SYSCALLS__ 24 + 25 + #include <linux/module.h> 26 + #include <linux/fs.h> 27 + #include <linux/mm.h> 28 + #include <linux/slab.h> 29 + #include <linux/unistd.h> 30 + #include <linux/netdevice.h> 31 + #include <linux/timer.h> 32 + #include <linux/delay.h> 33 + #include <linux/slab.h> 34 + #include <asm/io.h> 35 + #include <asm/uaccess.h> 36 + #include <linux/vmalloc.h> 37 + 38 + #include "ft1000_dev.h" 39 + #include "ft1000.h" 40 + #include "boot.h" 41 + 42 + #ifdef FT_DEBUG 43 + #define DEBUG(n, args...) printk(KERN_DEBUG args); 44 + #else 45 + #define DEBUG(n, args...) 46 + #endif 47 + 48 + #define MAX_DSP_WAIT_LOOPS 100 49 + #define DSP_WAIT_SLEEP_TIME 1 /* 1 millisecond */ 50 + 51 + #define MAX_LENGTH 0x7f0 52 + 53 + #define DWNLD_MAG_HANDSHAKE_LOC 0x00 54 + #define DWNLD_MAG_TYPE_LOC 0x01 55 + #define DWNLD_MAG_SIZE_LOC 0x02 56 + #define DWNLD_MAG_PS_HDR_LOC 0x03 57 + 58 + #define DWNLD_HANDSHAKE_LOC 0x02 59 + #define DWNLD_TYPE_LOC 0x04 60 + #define DWNLD_SIZE_MSW_LOC 0x06 61 + #define DWNLD_SIZE_LSW_LOC 0x08 62 + #define DWNLD_PS_HDR_LOC 0x0A 63 + 64 + #define HANDSHAKE_TIMEOUT_VALUE 0xF1F1 65 + #define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */ 66 + #define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */ 67 + #define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */ 68 + #define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */ 69 + 70 + #define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */ 71 + #define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */ 72 + 73 + #define REQUEST_CODE_LENGTH 0x0000 74 + #define REQUEST_RUN_ADDRESS 0x0001 75 + #define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */ 76 + #define REQUEST_DONE_BL 0x0003 77 + #define REQUEST_DONE_CL 0x0004 78 + #define REQUEST_VERSION_INFO 0x0005 79 + #define REQUEST_CODE_BY_VERSION 0x0006 80 + #define REQUEST_MAILBOX_DATA 0x0007 81 + #define REQUEST_FILE_CHECKSUM 0x0008 82 + 83 + #define STATE_START_DWNLD 0x01 84 + #define STATE_BOOT_DWNLD 0x02 85 + #define STATE_CODE_DWNLD 0x03 86 + #define STATE_DONE_DWNLD 0x04 87 + #define STATE_SECTION_PROV 0x05 88 + #define STATE_DONE_PROV 0x06 89 + #define STATE_DONE_FILE 0x07 90 + 91 + USHORT get_handshake(struct net_device *dev, USHORT expected_value); 92 + void put_handshake(struct net_device *dev, USHORT handshake_value); 93 + USHORT get_request_type(struct net_device *dev); 94 + long get_request_value(struct net_device *dev); 95 + void put_request_value(struct net_device *dev, long lvalue); 96 + USHORT hdr_checksum(PPSEUDO_HDR pHdr); 97 + 98 + typedef struct _DSP_FILE_HDR { 99 + long build_date; 100 + long dsp_coff_date; 101 + long loader_code_address; 102 + long loader_code_size; 103 + long loader_code_end; 104 + long dsp_code_address; 105 + long dsp_code_size; 106 + long dsp_code_end; 107 + long reserved[8]; 108 + } __attribute__ ((packed)) DSP_FILE_HDR, *PDSP_FILE_HDR; 109 + 110 + typedef struct _DSP_FILE_HDR_5 { 111 + long version_id; // Version ID of this image format. 112 + long package_id; // Package ID of code release. 113 + long build_date; // Date/time stamp when file was built. 114 + long commands_offset; // Offset to attached commands in Pseudo Hdr format. 115 + long loader_offset; // Offset to bootloader code. 116 + long loader_code_address; // Start address of bootloader. 117 + long loader_code_end; // Where bootloader code ends. 118 + long loader_code_size; 119 + long version_data_offset; // Offset were scrambled version data begins. 120 + long version_data_size; // Size, in words, of scrambled version data. 121 + long nDspImages; // Number of DSP images in file. 122 + } __attribute__ ((packed)) DSP_FILE_HDR_5, *PDSP_FILE_HDR_5; 123 + 124 + typedef struct _DSP_IMAGE_INFO { 125 + long coff_date; // Date/time when DSP Coff image was built. 126 + long begin_offset; // Offset in file where image begins. 127 + long end_offset; // Offset in file where image begins. 128 + long run_address; // On chip Start address of DSP code. 129 + long image_size; // Size of image. 130 + long version; // Embedded version # of DSP code. 131 + } __attribute__ ((packed)) DSP_IMAGE_INFO, *PDSP_IMAGE_INFO; 132 + 133 + typedef struct _DSP_IMAGE_INFO_V6 { 134 + long coff_date; // Date/time when DSP Coff image was built. 135 + long begin_offset; // Offset in file where image begins. 136 + long end_offset; // Offset in file where image begins. 137 + long run_address; // On chip Start address of DSP code. 138 + long image_size; // Size of image. 139 + long version; // Embedded version # of DSP code. 140 + unsigned short checksum; // Dsp File checksum 141 + unsigned short pad1; 142 + } __attribute__ ((packed)) DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6; 143 + 144 + void card_bootload(struct net_device *dev) 145 + { 146 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 147 + unsigned long flags; 148 + PULONG pdata; 149 + UINT size; 150 + UINT i; 151 + ULONG templong; 152 + 153 + DEBUG(0, "card_bootload is called\n"); 154 + 155 + pdata = (PULONG) bootimage; 156 + size = sizeof(bootimage); 157 + 158 + // check for odd word 159 + if (size & 0x0003) { 160 + size += 4; 161 + } 162 + // Provide mutual exclusive access while reading ASIC registers. 163 + spin_lock_irqsave(&info->dpram_lock, flags); 164 + 165 + // need to set i/o base address initially and hardware will autoincrement 166 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_BASE); 167 + // write bytes 168 + for (i = 0; i < (size >> 2); i++) { 169 + templong = *pdata++; 170 + outl(templong, dev->base_addr + FT1000_REG_MAG_DPDATA); 171 + } 172 + 173 + spin_unlock_irqrestore(&info->dpram_lock, flags); 174 + } 175 + 176 + USHORT get_handshake(struct net_device *dev, USHORT expected_value) 177 + { 178 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 179 + USHORT handshake; 180 + ULONG tempx; 181 + int loopcnt; 182 + 183 + loopcnt = 0; 184 + while (loopcnt < MAX_DSP_WAIT_LOOPS) { 185 + if (info->AsicID == ELECTRABUZZ_ID) { 186 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 187 + DWNLD_HANDSHAKE_LOC); 188 + 189 + handshake = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 190 + } else { 191 + tempx = 192 + ntohl(ft1000_read_dpram_mag_32 193 + (dev, DWNLD_MAG_HANDSHAKE_LOC)); 194 + handshake = (USHORT) tempx; 195 + } 196 + 197 + if ((handshake == expected_value) 198 + || (handshake == HANDSHAKE_RESET_VALUE)) { 199 + return handshake; 200 + } else { 201 + loopcnt++; 202 + mdelay(DSP_WAIT_SLEEP_TIME); 203 + } 204 + 205 + } 206 + 207 + return HANDSHAKE_TIMEOUT_VALUE; 208 + 209 + } 210 + 211 + void put_handshake(struct net_device *dev, USHORT handshake_value) 212 + { 213 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 214 + ULONG tempx; 215 + 216 + if (info->AsicID == ELECTRABUZZ_ID) { 217 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 218 + DWNLD_HANDSHAKE_LOC); 219 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value); /* Handshake */ 220 + } else { 221 + tempx = (ULONG) handshake_value; 222 + tempx = ntohl(tempx); 223 + ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */ 224 + } 225 + } 226 + 227 + USHORT get_request_type(struct net_device *dev) 228 + { 229 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 230 + USHORT request_type; 231 + ULONG tempx; 232 + 233 + if (info->AsicID == ELECTRABUZZ_ID) { 234 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC); 235 + request_type = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 236 + } else { 237 + tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC); 238 + tempx = ntohl(tempx); 239 + request_type = (USHORT) tempx; 240 + } 241 + 242 + return request_type; 243 + 244 + } 245 + 246 + long get_request_value(struct net_device *dev) 247 + { 248 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 249 + long value; 250 + USHORT w_val; 251 + 252 + if (info->AsicID == ELECTRABUZZ_ID) { 253 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 254 + DWNLD_SIZE_MSW_LOC); 255 + 256 + w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 257 + 258 + value = (long)(w_val << 16); 259 + 260 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 261 + DWNLD_SIZE_LSW_LOC); 262 + 263 + w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 264 + 265 + value = (long)(value | w_val); 266 + } else { 267 + value = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC); 268 + value = ntohl(value); 269 + } 270 + 271 + return value; 272 + 273 + } 274 + 275 + void put_request_value(struct net_device *dev, long lvalue) 276 + { 277 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 278 + USHORT size; 279 + ULONG tempx; 280 + 281 + if (info->AsicID == ELECTRABUZZ_ID) { 282 + size = (USHORT) (lvalue >> 16); 283 + 284 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 285 + DWNLD_SIZE_MSW_LOC); 286 + 287 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size); 288 + 289 + size = (USHORT) (lvalue); 290 + 291 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 292 + DWNLD_SIZE_LSW_LOC); 293 + 294 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size); 295 + } else { 296 + tempx = ntohl(lvalue); 297 + ft1000_write_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC, tempx); /* Handshake */ 298 + } 299 + 300 + } 301 + 302 + USHORT hdr_checksum(PPSEUDO_HDR pHdr) 303 + { 304 + USHORT *usPtr = (USHORT *) pHdr; 305 + USHORT chksum; 306 + 307 + chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^ 308 + usPtr[4]) ^ usPtr[5]) ^ usPtr[6]); 309 + 310 + return chksum; 311 + } 312 + 313 + int card_download(struct net_device *dev, void *pFileStart, UINT FileLength) 314 + { 315 + FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev); 316 + int Status = SUCCESS; 317 + USHORT DspWordCnt = 0; 318 + UINT uiState; 319 + USHORT handshake; 320 + PPSEUDO_HDR pHdr; 321 + USHORT usHdrLength; 322 + PDSP_FILE_HDR pFileHdr; 323 + long word_length; 324 + USHORT request; 325 + USHORT temp; 326 + PPROV_RECORD pprov_record; 327 + PUCHAR pbuffer; 328 + PDSP_FILE_HDR_5 pFileHdr5; 329 + PDSP_IMAGE_INFO pDspImageInfo = NULL; 330 + PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL; 331 + long requested_version; 332 + BOOLEAN bGoodVersion = 0; 333 + PDRVMSG pMailBoxData; 334 + USHORT *pUsData = NULL; 335 + USHORT *pUsFile = NULL; 336 + UCHAR *pUcFile = NULL; 337 + UCHAR *pBootEnd = NULL; 338 + UCHAR *pCodeEnd = NULL; 339 + int imageN; 340 + long file_version; 341 + long loader_code_address = 0; 342 + long loader_code_size = 0; 343 + long run_address = 0; 344 + long run_size = 0; 345 + unsigned long flags; 346 + unsigned long templong; 347 + unsigned long image_chksum = 0; 348 + 349 + // 350 + // Get version id of file, at first 4 bytes of file, for newer files. 351 + // 352 + file_version = *(long *)pFileStart; 353 + 354 + uiState = STATE_START_DWNLD; 355 + 356 + pFileHdr = (PDSP_FILE_HDR) pFileStart; 357 + pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart; 358 + 359 + switch (file_version) { 360 + case 5: 361 + case 6: 362 + pUsFile = 363 + (USHORT *) ((long)pFileStart + pFileHdr5->loader_offset); 364 + pUcFile = 365 + (UCHAR *) ((long)pFileStart + pFileHdr5->loader_offset); 366 + 367 + pBootEnd = 368 + (UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end); 369 + 370 + loader_code_address = pFileHdr5->loader_code_address; 371 + loader_code_size = pFileHdr5->loader_code_size; 372 + bGoodVersion = FALSE; 373 + break; 374 + 375 + default: 376 + Status = FAILURE; 377 + break; 378 + } 379 + 380 + while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) { 381 + 382 + switch (uiState) { 383 + case STATE_START_DWNLD: 384 + 385 + handshake = get_handshake(dev, HANDSHAKE_DSP_BL_READY); 386 + 387 + if (handshake == HANDSHAKE_DSP_BL_READY) { 388 + put_handshake(dev, HANDSHAKE_DRIVER_READY); 389 + } else { 390 + Status = FAILURE; 391 + } 392 + 393 + uiState = STATE_BOOT_DWNLD; 394 + 395 + break; 396 + 397 + case STATE_BOOT_DWNLD: 398 + handshake = get_handshake(dev, HANDSHAKE_REQUEST); 399 + if (handshake == HANDSHAKE_REQUEST) { 400 + /* 401 + * Get type associated with the request. 402 + */ 403 + request = get_request_type(dev); 404 + switch (request) { 405 + case REQUEST_RUN_ADDRESS: 406 + put_request_value(dev, 407 + loader_code_address); 408 + break; 409 + case REQUEST_CODE_LENGTH: 410 + put_request_value(dev, 411 + loader_code_size); 412 + break; 413 + case REQUEST_DONE_BL: 414 + /* Reposition ptrs to beginning of code section */ 415 + pUsFile = (USHORT *) ((long)pBootEnd); 416 + pUcFile = (UCHAR *) ((long)pBootEnd); 417 + uiState = STATE_CODE_DWNLD; 418 + break; 419 + case REQUEST_CODE_SEGMENT: 420 + word_length = get_request_value(dev); 421 + if (word_length > MAX_LENGTH) { 422 + Status = FAILURE; 423 + break; 424 + } 425 + if ((word_length * 2 + (long)pUcFile) > 426 + (long)pBootEnd) { 427 + /* 428 + * Error, beyond boot code range. 429 + */ 430 + Status = FAILURE; 431 + break; 432 + } 433 + // Provide mutual exclusive access while reading ASIC registers. 434 + spin_lock_irqsave(&info->dpram_lock, 435 + flags); 436 + if (file_version == 5) { 437 + /* 438 + * Position ASIC DPRAM auto-increment pointer. 439 + */ 440 + ft1000_write_reg(dev, 441 + FT1000_REG_DPRAM_ADDR, 442 + DWNLD_PS_HDR_LOC); 443 + 444 + for (; word_length > 0; word_length--) { /* In words */ 445 + //temp = *pUsFile; 446 + //temp = RtlUshortByteSwap(temp); 447 + ft1000_write_reg(dev, 448 + FT1000_REG_DPRAM_DATA, 449 + *pUsFile); 450 + pUsFile++; 451 + pUcFile += 2; 452 + DspWordCnt++; 453 + } 454 + } else { 455 + /* 456 + * Position ASIC DPRAM auto-increment pointer. 457 + */ 458 + outw(DWNLD_MAG_PS_HDR_LOC, 459 + dev->base_addr + 460 + FT1000_REG_DPRAM_ADDR); 461 + if (word_length & 0x01) { 462 + word_length++; 463 + } 464 + word_length = word_length / 2; 465 + 466 + for (; word_length > 0; word_length--) { /* In words */ 467 + templong = *pUsFile++; 468 + templong |= 469 + (*pUsFile++ << 16); 470 + pUcFile += 4; 471 + outl(templong, 472 + dev->base_addr + 473 + FT1000_REG_MAG_DPDATAL); 474 + } 475 + } 476 + spin_unlock_irqrestore(&info-> 477 + dpram_lock, 478 + flags); 479 + break; 480 + default: 481 + Status = FAILURE; 482 + break; 483 + } 484 + put_handshake(dev, HANDSHAKE_RESPONSE); 485 + } else { 486 + Status = FAILURE; 487 + } 488 + 489 + break; 490 + 491 + case STATE_CODE_DWNLD: 492 + handshake = get_handshake(dev, HANDSHAKE_REQUEST); 493 + if (handshake == HANDSHAKE_REQUEST) { 494 + /* 495 + * Get type associated with the request. 496 + */ 497 + request = get_request_type(dev); 498 + switch (request) { 499 + case REQUEST_FILE_CHECKSUM: 500 + DEBUG(0, 501 + "ft1000_dnld: REQUEST_FOR_CHECKSUM\n"); 502 + put_request_value(dev, image_chksum); 503 + break; 504 + case REQUEST_RUN_ADDRESS: 505 + if (bGoodVersion) { 506 + put_request_value(dev, 507 + run_address); 508 + } else { 509 + Status = FAILURE; 510 + break; 511 + } 512 + break; 513 + case REQUEST_CODE_LENGTH: 514 + if (bGoodVersion) { 515 + put_request_value(dev, 516 + run_size); 517 + } else { 518 + Status = FAILURE; 519 + break; 520 + } 521 + break; 522 + case REQUEST_DONE_CL: 523 + /* Reposition ptrs to beginning of provisioning section */ 524 + switch (file_version) { 525 + case 5: 526 + case 6: 527 + pUsFile = 528 + (USHORT *) ((long)pFileStart 529 + + 530 + pFileHdr5-> 531 + commands_offset); 532 + pUcFile = 533 + (UCHAR *) ((long)pFileStart 534 + + 535 + pFileHdr5-> 536 + commands_offset); 537 + break; 538 + default: 539 + Status = FAILURE; 540 + break; 541 + } 542 + uiState = STATE_DONE_DWNLD; 543 + break; 544 + case REQUEST_CODE_SEGMENT: 545 + if (!bGoodVersion) { 546 + Status = FAILURE; 547 + break; 548 + } 549 + word_length = get_request_value(dev); 550 + if (word_length > MAX_LENGTH) { 551 + Status = FAILURE; 552 + break; 553 + } 554 + if ((word_length * 2 + (long)pUcFile) > 555 + (long)pCodeEnd) { 556 + /* 557 + * Error, beyond boot code range. 558 + */ 559 + Status = FAILURE; 560 + break; 561 + } 562 + if (file_version == 5) { 563 + /* 564 + * Position ASIC DPRAM auto-increment pointer. 565 + */ 566 + ft1000_write_reg(dev, 567 + FT1000_REG_DPRAM_ADDR, 568 + DWNLD_PS_HDR_LOC); 569 + 570 + for (; word_length > 0; word_length--) { /* In words */ 571 + //temp = *pUsFile; 572 + //temp = RtlUshortByteSwap(temp); 573 + ft1000_write_reg(dev, 574 + FT1000_REG_DPRAM_DATA, 575 + *pUsFile); 576 + pUsFile++; 577 + pUcFile += 2; 578 + DspWordCnt++; 579 + } 580 + } else { 581 + /* 582 + * Position ASIC DPRAM auto-increment pointer. 583 + */ 584 + outw(DWNLD_MAG_PS_HDR_LOC, 585 + dev->base_addr + 586 + FT1000_REG_DPRAM_ADDR); 587 + if (word_length & 0x01) { 588 + word_length++; 589 + } 590 + word_length = word_length / 2; 591 + 592 + for (; word_length > 0; word_length--) { /* In words */ 593 + templong = *pUsFile++; 594 + templong |= 595 + (*pUsFile++ << 16); 596 + pUcFile += 4; 597 + outl(templong, 598 + dev->base_addr + 599 + FT1000_REG_MAG_DPDATAL); 600 + } 601 + } 602 + break; 603 + 604 + case REQUEST_MAILBOX_DATA: 605 + // Convert length from byte count to word count. Make sure we round up. 606 + word_length = 607 + (long)(info->DSPInfoBlklen + 1) / 2; 608 + put_request_value(dev, word_length); 609 + pMailBoxData = 610 + (PDRVMSG) & info->DSPInfoBlk[0]; 611 + pUsData = 612 + (USHORT *) & pMailBoxData->data[0]; 613 + // Provide mutual exclusive access while reading ASIC registers. 614 + spin_lock_irqsave(&info->dpram_lock, 615 + flags); 616 + if (file_version == 5) { 617 + /* 618 + * Position ASIC DPRAM auto-increment pointer. 619 + */ 620 + ft1000_write_reg(dev, 621 + FT1000_REG_DPRAM_ADDR, 622 + DWNLD_PS_HDR_LOC); 623 + 624 + for (; word_length > 0; word_length--) { /* In words */ 625 + temp = ntohs(*pUsData); 626 + ft1000_write_reg(dev, 627 + FT1000_REG_DPRAM_DATA, 628 + temp); 629 + pUsData++; 630 + } 631 + } else { 632 + /* 633 + * Position ASIC DPRAM auto-increment pointer. 634 + */ 635 + outw(DWNLD_MAG_PS_HDR_LOC, 636 + dev->base_addr + 637 + FT1000_REG_DPRAM_ADDR); 638 + if (word_length & 0x01) { 639 + word_length++; 640 + } 641 + word_length = word_length / 2; 642 + 643 + for (; word_length > 0; word_length--) { /* In words */ 644 + templong = *pUsData++; 645 + templong |= 646 + (*pUsData++ << 16); 647 + outl(templong, 648 + dev->base_addr + 649 + FT1000_REG_MAG_DPDATAL); 650 + } 651 + } 652 + spin_unlock_irqrestore(&info-> 653 + dpram_lock, 654 + flags); 655 + break; 656 + 657 + case REQUEST_VERSION_INFO: 658 + word_length = 659 + pFileHdr5->version_data_size; 660 + put_request_value(dev, word_length); 661 + pUsFile = 662 + (USHORT *) ((long)pFileStart + 663 + pFileHdr5-> 664 + version_data_offset); 665 + // Provide mutual exclusive access while reading ASIC registers. 666 + spin_lock_irqsave(&info->dpram_lock, 667 + flags); 668 + if (file_version == 5) { 669 + /* 670 + * Position ASIC DPRAM auto-increment pointer. 671 + */ 672 + ft1000_write_reg(dev, 673 + FT1000_REG_DPRAM_ADDR, 674 + DWNLD_PS_HDR_LOC); 675 + 676 + for (; word_length > 0; word_length--) { /* In words */ 677 + ft1000_write_reg(dev, 678 + FT1000_REG_DPRAM_DATA, 679 + *pUsFile 680 + /*temp */ 681 + ); 682 + pUsFile++; 683 + } 684 + } else { 685 + /* 686 + * Position ASIC DPRAM auto-increment pointer. 687 + */ 688 + outw(DWNLD_MAG_PS_HDR_LOC, 689 + dev->base_addr + 690 + FT1000_REG_DPRAM_ADDR); 691 + if (word_length & 0x01) { 692 + word_length++; 693 + } 694 + word_length = word_length / 2; 695 + 696 + for (; word_length > 0; word_length--) { /* In words */ 697 + templong = 698 + ntohs(*pUsFile++); 699 + temp = 700 + ntohs(*pUsFile++); 701 + templong |= 702 + (temp << 16); 703 + outl(templong, 704 + dev->base_addr + 705 + FT1000_REG_MAG_DPDATAL); 706 + } 707 + } 708 + spin_unlock_irqrestore(&info-> 709 + dpram_lock, 710 + flags); 711 + break; 712 + 713 + case REQUEST_CODE_BY_VERSION: 714 + bGoodVersion = FALSE; 715 + requested_version = 716 + get_request_value(dev); 717 + if (file_version == 5) { 718 + pDspImageInfo = 719 + (PDSP_IMAGE_INFO) ((long) 720 + pFileStart 721 + + 722 + sizeof 723 + (DSP_FILE_HDR_5)); 724 + for (imageN = 0; 725 + imageN < 726 + pFileHdr5->nDspImages; 727 + imageN++) { 728 + if (pDspImageInfo-> 729 + version == 730 + requested_version) { 731 + bGoodVersion = 732 + TRUE; 733 + pUsFile = 734 + (USHORT 735 + *) ((long) 736 + pFileStart 737 + + 738 + pDspImageInfo-> 739 + begin_offset); 740 + pUcFile = 741 + (UCHAR 742 + *) ((long) 743 + pFileStart 744 + + 745 + pDspImageInfo-> 746 + begin_offset); 747 + pCodeEnd = 748 + (UCHAR 749 + *) ((long) 750 + pFileStart 751 + + 752 + pDspImageInfo-> 753 + end_offset); 754 + run_address = 755 + pDspImageInfo-> 756 + run_address; 757 + run_size = 758 + pDspImageInfo-> 759 + image_size; 760 + break; 761 + } 762 + pDspImageInfo++; 763 + } 764 + } else { 765 + pDspImageInfoV6 = 766 + (PDSP_IMAGE_INFO_V6) ((long) 767 + pFileStart 768 + + 769 + sizeof 770 + (DSP_FILE_HDR_5)); 771 + for (imageN = 0; 772 + imageN < 773 + pFileHdr5->nDspImages; 774 + imageN++) { 775 + temp = (USHORT) 776 + (pDspImageInfoV6-> 777 + version); 778 + templong = temp; 779 + temp = (USHORT) 780 + (pDspImageInfoV6-> 781 + version >> 16); 782 + templong |= 783 + (temp << 16); 784 + if (templong == 785 + requested_version) { 786 + bGoodVersion = 787 + TRUE; 788 + pUsFile = 789 + (USHORT 790 + *) ((long) 791 + pFileStart 792 + + 793 + pDspImageInfoV6-> 794 + begin_offset); 795 + pUcFile = 796 + (UCHAR 797 + *) ((long) 798 + pFileStart 799 + + 800 + pDspImageInfoV6-> 801 + begin_offset); 802 + pCodeEnd = 803 + (UCHAR 804 + *) ((long) 805 + pFileStart 806 + + 807 + pDspImageInfoV6-> 808 + end_offset); 809 + run_address = 810 + pDspImageInfoV6-> 811 + run_address; 812 + run_size = 813 + pDspImageInfoV6-> 814 + image_size; 815 + image_chksum = 816 + (ULONG) 817 + pDspImageInfoV6-> 818 + checksum; 819 + DEBUG(0, 820 + "ft1000_dnld: image_chksum = 0x%8x\n", 821 + (unsigned 822 + int) 823 + image_chksum); 824 + break; 825 + } 826 + pDspImageInfoV6++; 827 + } 828 + } 829 + if (!bGoodVersion) { 830 + /* 831 + * Error, beyond boot code range. 832 + */ 833 + Status = FAILURE; 834 + break; 835 + } 836 + break; 837 + 838 + default: 839 + Status = FAILURE; 840 + break; 841 + } 842 + put_handshake(dev, HANDSHAKE_RESPONSE); 843 + } else { 844 + Status = FAILURE; 845 + } 846 + 847 + break; 848 + 849 + case STATE_DONE_DWNLD: 850 + if (((UINT) (pUcFile) - (UINT) pFileStart) >= 851 + (UINT) FileLength) { 852 + uiState = STATE_DONE_FILE; 853 + break; 854 + } 855 + 856 + pHdr = (PPSEUDO_HDR) pUsFile; 857 + 858 + if (pHdr->portdest == 0x80 /* DspOAM */ 859 + && (pHdr->portsrc == 0x00 /* Driver */ 860 + || pHdr->portsrc == 0x10 /* FMM */ )) { 861 + uiState = STATE_SECTION_PROV; 862 + } else { 863 + DEBUG(1, 864 + "FT1000:download:Download error: Bad Port IDs in Pseudo Record\n"); 865 + DEBUG(1, "\t Port Source = 0x%2.2x\n", 866 + pHdr->portsrc); 867 + DEBUG(1, "\t Port Destination = 0x%2.2x\n", 868 + pHdr->portdest); 869 + Status = FAILURE; 870 + } 871 + 872 + break; 873 + 874 + case STATE_SECTION_PROV: 875 + 876 + pHdr = (PPSEUDO_HDR) pUcFile; 877 + 878 + if (pHdr->checksum == hdr_checksum(pHdr)) { 879 + if (pHdr->portdest != 0x80 /* Dsp OAM */ ) { 880 + uiState = STATE_DONE_PROV; 881 + break; 882 + } 883 + usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */ 884 + 885 + // Get buffer for provisioning data 886 + pbuffer = 887 + kmalloc((usHdrLength + sizeof(PSEUDO_HDR)), 888 + GFP_ATOMIC); 889 + if (pbuffer) { 890 + memcpy(pbuffer, (void *)pUcFile, 891 + (UINT) (usHdrLength + 892 + sizeof(PSEUDO_HDR))); 893 + // link provisioning data 894 + pprov_record = 895 + kmalloc(sizeof(PROV_RECORD), 896 + GFP_ATOMIC); 897 + if (pprov_record) { 898 + pprov_record->pprov_data = 899 + pbuffer; 900 + list_add_tail(&pprov_record-> 901 + list, 902 + &info->prov_list); 903 + // Move to next entry if available 904 + pUcFile = 905 + (UCHAR *) ((UINT) pUcFile + 906 + (UINT) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR)); 907 + if ((UINT) (pUcFile) - 908 + (UINT) (pFileStart) >= 909 + (UINT) FileLength) { 910 + uiState = 911 + STATE_DONE_FILE; 912 + } 913 + } else { 914 + kfree(pbuffer); 915 + Status = FAILURE; 916 + } 917 + } else { 918 + Status = FAILURE; 919 + } 920 + } else { 921 + /* Checksum did not compute */ 922 + Status = FAILURE; 923 + } 924 + 925 + break; 926 + 927 + case STATE_DONE_PROV: 928 + uiState = STATE_DONE_FILE; 929 + break; 930 + 931 + default: 932 + Status = FAILURE; 933 + break; 934 + } /* End Switch */ 935 + 936 + } /* End while */ 937 + 938 + return Status; 939 + 940 + }
+2286
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
··· 1 + /*--------------------------------------------------------------------------- 2 + FT1000 driver for Flarion Flash OFDM NIC Device 3 + 4 + Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + Copyright (C) 2006 Patrik Ostrihon, All rights reserved. 6 + Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved. 7 + 8 + This program is free software; you can redistribute it and/or modify it 9 + under the terms of the GNU General Public License as published by the Free 10 + Software Foundation; either version 2 of the License, or (at your option) any 11 + later version. This program is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + more details. You should have received a copy of the GNU General Public 15 + License along with this program; if not, write to the 16 + Free Software Foundation, Inc., 59 Temple Place - 17 + Suite 330, Boston, MA 02111-1307, USA. 18 + -----------------------------------------------------------------------------*/ 19 + 20 + #include <linux/kernel.h> 21 + #include <linux/module.h> 22 + #include <linux/proc_fs.h> 23 + 24 + #include <linux/sched.h> 25 + #include <linux/ptrace.h> 26 + #include <linux/slab.h> 27 + #include <linux/string.h> 28 + #include <linux/timer.h> 29 + #include <linux/interrupt.h> 30 + #include <linux/in.h> 31 + #include <asm/io.h> 32 + #include <asm/system.h> 33 + #include <asm/bitops.h> 34 + 35 + #include <linux/netdevice.h> 36 + #include <linux/etherdevice.h> 37 + #include <linux/skbuff.h> 38 + #include <linux/if_arp.h> 39 + #include <linux/ioport.h> 40 + #include <linux/wait.h> 41 + #include <linux/vmalloc.h> 42 + 43 + #include <linux/firmware.h> 44 + #include <linux/ethtool.h> 45 + 46 + #ifdef FT_DEBUG 47 + #define DEBUG(n, args...) printk(KERN_DEBUG args); 48 + #else 49 + #define DEBUG(n, args...) 50 + #endif 51 + 52 + #include <linux/delay.h> 53 + #include "ft1000_dev.h" 54 + #include "ft1000.h" 55 + 56 + int card_download(struct net_device *dev, void *pFileStart, UINT FileLength); 57 + 58 + void ft1000InitProc(struct net_device *dev); 59 + void ft1000CleanupProc(struct net_device *dev); 60 + 61 + const struct firmware *fw_entry; 62 + 63 + static void ft1000_hbchk(u_long data); 64 + static struct timer_list poll_timer = { 65 + function:ft1000_hbchk 66 + }; 67 + 68 + static u16 cmdbuffer[1024]; 69 + static u8 tempbuffer[1600]; 70 + static u8 ft1000_card_present = 0; 71 + static u8 flarion_ft1000_cnt = 0; 72 + 73 + static irqreturn_t ft1000_interrupt(int irq, void *dev_id); 74 + static void ft1000_enable_interrupts(struct net_device *dev); 75 + static void ft1000_disable_interrupts(struct net_device *dev); 76 + 77 + /* new kernel */ 78 + MODULE_AUTHOR(""); 79 + MODULE_DESCRIPTION 80 + ("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs."); 81 + MODULE_LICENSE("GPL"); 82 + MODULE_SUPPORTED_DEVICE("FT1000"); 83 + 84 + #define MAX_RCV_LOOP 100 85 + 86 + //--------------------------------------------------------------------------- 87 + // 88 + // Function: ft1000_asic_read 89 + // Descripton: This function will retrieve the value of a specific ASIC 90 + // register. 91 + // Input: 92 + // dev - network device structure 93 + // offset - ASIC register to read 94 + // Output: 95 + // value - value of ASIC register 96 + // 97 + //--------------------------------------------------------------------------- 98 + inline u16 ft1000_asic_read(struct net_device *dev, u16 offset) 99 + { 100 + return (ft1000_read_reg(dev, offset)); 101 + } 102 + 103 + //--------------------------------------------------------------------------- 104 + // 105 + // Function: ft1000_asic_write 106 + // Descripton: This function will set the value of a specific ASIC 107 + // register. 108 + // Input: 109 + // dev - network device structure 110 + // value - value to set ASIC register 111 + // Output: 112 + // none 113 + // 114 + //--------------------------------------------------------------------------- 115 + inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value) 116 + { 117 + ft1000_write_reg(dev, offset, value); 118 + } 119 + 120 + //--------------------------------------------------------------------------- 121 + // 122 + // Function: ft1000_read_fifo_len 123 + // Descripton: This function will read the ASIC Uplink FIFO status register 124 + // which will return the number of bytes remaining in the Uplink FIFO. 125 + // Sixteen bytes are subtracted to make sure that the ASIC does not 126 + // reach its threshold. 127 + // Input: 128 + // dev - network device structure 129 + // Output: 130 + // value - number of bytes available in the ASIC Uplink FIFO. 131 + // 132 + //--------------------------------------------------------------------------- 133 + static inline u16 ft1000_read_fifo_len(struct net_device *dev) 134 + { 135 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 136 + 137 + if (info->AsicID == ELECTRABUZZ_ID) { 138 + return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16); 139 + } else { 140 + return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16); 141 + } 142 + } 143 + 144 + //--------------------------------------------------------------------------- 145 + // 146 + // Function: ft1000_read_dpram 147 + // Descripton: This function will read the specific area of dpram 148 + // (Electrabuzz ASIC only) 149 + // Input: 150 + // dev - device structure 151 + // offset - index of dpram 152 + // Output: 153 + // value - value of dpram 154 + // 155 + //--------------------------------------------------------------------------- 156 + u16 ft1000_read_dpram(struct net_device * dev, int offset) 157 + { 158 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 159 + unsigned long flags; 160 + u16 data; 161 + 162 + // Provide mutual exclusive access while reading ASIC registers. 163 + spin_lock_irqsave(&info->dpram_lock, flags); 164 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 165 + data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 166 + spin_unlock_irqrestore(&info->dpram_lock, flags); 167 + 168 + return (data); 169 + } 170 + 171 + //--------------------------------------------------------------------------- 172 + // 173 + // Function: ft1000_write_dpram 174 + // Descripton: This function will write to a specific area of dpram 175 + // (Electrabuzz ASIC only) 176 + // Input: 177 + // dev - device structure 178 + // offset - index of dpram 179 + // value - value to write 180 + // Output: 181 + // none. 182 + // 183 + //--------------------------------------------------------------------------- 184 + static inline void ft1000_write_dpram(struct net_device *dev, 185 + int offset, u16 value) 186 + { 187 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 188 + unsigned long flags; 189 + 190 + // Provide mutual exclusive access while reading ASIC registers. 191 + spin_lock_irqsave(&info->dpram_lock, flags); 192 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 193 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value); 194 + spin_unlock_irqrestore(&info->dpram_lock, flags); 195 + } 196 + 197 + //--------------------------------------------------------------------------- 198 + // 199 + // Function: ft1000_read_dpram_mag_16 200 + // Descripton: This function will read the specific area of dpram 201 + // (Magnemite ASIC only) 202 + // Input: 203 + // dev - device structure 204 + // offset - index of dpram 205 + // Output: 206 + // value - value of dpram 207 + // 208 + //--------------------------------------------------------------------------- 209 + u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) 210 + { 211 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 212 + unsigned long flags; 213 + u16 data; 214 + 215 + // Provide mutual exclusive access while reading ASIC registers. 216 + spin_lock_irqsave(&info->dpram_lock, flags); 217 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 218 + // check if we want to read upper or lower 32-bit word 219 + if (Index) { 220 + data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL); 221 + } else { 222 + data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH); 223 + } 224 + spin_unlock_irqrestore(&info->dpram_lock, flags); 225 + 226 + return (data); 227 + } 228 + 229 + //--------------------------------------------------------------------------- 230 + // 231 + // Function: ft1000_write_dpram_mag_16 232 + // Descripton: This function will write to a specific area of dpram 233 + // (Magnemite ASIC only) 234 + // Input: 235 + // dev - device structure 236 + // offset - index of dpram 237 + // value - value to write 238 + // Output: 239 + // none. 240 + // 241 + //--------------------------------------------------------------------------- 242 + static inline void ft1000_write_dpram_mag_16(struct net_device *dev, 243 + int offset, u16 value, int Index) 244 + { 245 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 246 + unsigned long flags; 247 + 248 + // Provide mutual exclusive access while reading ASIC registers. 249 + spin_lock_irqsave(&info->dpram_lock, flags); 250 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 251 + if (Index) { 252 + ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value); 253 + } else { 254 + ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value); 255 + } 256 + spin_unlock_irqrestore(&info->dpram_lock, flags); 257 + } 258 + 259 + //--------------------------------------------------------------------------- 260 + // 261 + // Function: ft1000_read_dpram_mag_32 262 + // Descripton: This function will read the specific area of dpram 263 + // (Magnemite ASIC only) 264 + // Input: 265 + // dev - device structure 266 + // offset - index of dpram 267 + // Output: 268 + // value - value of dpram 269 + // 270 + //--------------------------------------------------------------------------- 271 + u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset) 272 + { 273 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 274 + unsigned long flags; 275 + u32 data; 276 + 277 + // Provide mutual exclusive access while reading ASIC registers. 278 + spin_lock_irqsave(&info->dpram_lock, flags); 279 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 280 + data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL); 281 + spin_unlock_irqrestore(&info->dpram_lock, flags); 282 + 283 + return (data); 284 + } 285 + 286 + //--------------------------------------------------------------------------- 287 + // 288 + // Function: ft1000_write_dpram_mag_32 289 + // Descripton: This function will write to a specific area of dpram 290 + // (Magnemite ASIC only) 291 + // Input: 292 + // dev - device structure 293 + // offset - index of dpram 294 + // value - value to write 295 + // Output: 296 + // none. 297 + // 298 + //--------------------------------------------------------------------------- 299 + void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value) 300 + { 301 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 302 + unsigned long flags; 303 + 304 + // Provide mutual exclusive access while reading ASIC registers. 305 + spin_lock_irqsave(&info->dpram_lock, flags); 306 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); 307 + outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL); 308 + spin_unlock_irqrestore(&info->dpram_lock, flags); 309 + } 310 + 311 + //--------------------------------------------------------------------------- 312 + // 313 + // Function: ft1000_enable_interrupts 314 + // Descripton: This function will enable interrupts base on the current interrupt mask. 315 + // Input: 316 + // dev - device structure 317 + // Output: 318 + // None. 319 + // 320 + //--------------------------------------------------------------------------- 321 + static void ft1000_enable_interrupts(struct net_device *dev) 322 + { 323 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 324 + u16 tempword; 325 + 326 + DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n"); 327 + ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, 328 + info->CurrentInterruptEnableMask); 329 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK); 330 + DEBUG(1, 331 + "ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n", 332 + tempword); 333 + info->InterruptsEnabled = TRUE; 334 + } 335 + 336 + //--------------------------------------------------------------------------- 337 + // 338 + // Function: ft1000_disable_interrupts 339 + // Descripton: This function will disable all interrupts. 340 + // Input: 341 + // dev - device structure 342 + // Output: 343 + // None. 344 + // 345 + //--------------------------------------------------------------------------- 346 + static void ft1000_disable_interrupts(struct net_device *dev) 347 + { 348 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 349 + u16 tempword; 350 + 351 + DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n"); 352 + ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL); 353 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK); 354 + DEBUG(1, 355 + "ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n", 356 + tempword); 357 + info->InterruptsEnabled = FALSE; 358 + } 359 + 360 + //--------------------------------------------------------------------------- 361 + // 362 + // Function: ft1000_reset_asic 363 + // Descripton: This function will call the Card Service function to reset the 364 + // ASIC. 365 + // Input: 366 + // dev - device structure 367 + // Output: 368 + // none 369 + // 370 + //--------------------------------------------------------------------------- 371 + static void ft1000_reset_asic(struct net_device *dev) 372 + { 373 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 374 + u16 tempword; 375 + 376 + DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n"); 377 + 378 + (*info->ft1000_reset) (info->link); 379 + info->ASICResetNum++; 380 + 381 + // Let's use the register provided by the Magnemite ASIC to reset the 382 + // ASIC and DSP. 383 + if (info->AsicID == MAGNEMITE_ID) { 384 + ft1000_write_reg(dev, FT1000_REG_RESET, 385 + (DSP_RESET_BIT | ASIC_RESET_BIT)); 386 + } 387 + mdelay(1); 388 + if (info->AsicID == ELECTRABUZZ_ID) { 389 + // set watermark to -1 in order to not generate an interrrupt 390 + ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff); 391 + } else { 392 + // set watermark to -1 in order to not generate an interrrupt 393 + ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff); 394 + } 395 + // clear interrupts 396 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); 397 + DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); 398 + ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); 399 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); 400 + DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); 401 + 402 + } 403 + 404 + //--------------------------------------------------------------------------- 405 + // 406 + // Function: ft1000_reset_card 407 + // Descripton: This function will reset the card 408 + // Input: 409 + // dev - device structure 410 + // Output: 411 + // status - FALSE (card reset fail) 412 + // TRUE (card reset successful) 413 + // 414 + //--------------------------------------------------------------------------- 415 + static int ft1000_reset_card(struct net_device *dev) 416 + { 417 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 418 + u16 tempword; 419 + int i; 420 + unsigned long flags; 421 + PPROV_RECORD ptr; 422 + 423 + DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n"); 424 + 425 + info->CardReady = 0; 426 + info->ProgConStat = 0; 427 + info->squeseqnum = 0; 428 + ft1000_disable_interrupts(dev); 429 + 430 + // del_timer(&poll_timer); 431 + 432 + // Make sure we free any memory reserve for provisioning 433 + while (list_empty(&info->prov_list) == 0) { 434 + DEBUG(0, 435 + "ft1000_hw:ft1000_reset_card:deleting provisioning record\n"); 436 + ptr = list_entry(info->prov_list.next, PROV_RECORD, list); 437 + list_del(&ptr->list); 438 + kfree(ptr->pprov_data); 439 + kfree(ptr); 440 + } 441 + 442 + if (info->AsicID == ELECTRABUZZ_ID) { 443 + DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting DSP\n"); 444 + ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT); 445 + } else { 446 + DEBUG(1, 447 + "ft1000_hw:ft1000_reset_card:resetting ASIC and DSP\n"); 448 + ft1000_write_reg(dev, FT1000_REG_RESET, 449 + (DSP_RESET_BIT | ASIC_RESET_BIT)); 450 + } 451 + 452 + // Copy DSP session record into info block if this is not a coldstart 453 + if (ft1000_card_present == 1) { 454 + spin_lock_irqsave(&info->dpram_lock, flags); 455 + if (info->AsicID == ELECTRABUZZ_ID) { 456 + if (info->DspHibernateFlag == 0) { 457 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 458 + FT1000_DPRAM_RX_BASE); 459 + for (i = 0; i < MAX_DSP_SESS_REC; i++) { 460 + info->DSPSess.Rec[i] = 461 + ft1000_read_reg(dev, 462 + FT1000_REG_DPRAM_DATA); 463 + } 464 + } 465 + } else { 466 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 467 + FT1000_DPRAM_MAG_RX_BASE); 468 + for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) { 469 + info->DSPSess.MagRec[i] = 470 + inl(dev->base_addr + FT1000_REG_MAG_DPDATA); 471 + } 472 + } 473 + spin_unlock_irqrestore(&info->dpram_lock, flags); 474 + } 475 + 476 + DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting ASIC\n"); 477 + mdelay(10); 478 + //reset ASIC 479 + ft1000_reset_asic(dev); 480 + 481 + info->DSPResetNum++; 482 + 483 + DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n"); 484 + 485 + if (info->AsicID == MAGNEMITE_ID) { 486 + // Put dsp in reset and take ASIC out of reset 487 + DEBUG(0, 488 + "ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n"); 489 + ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT); 490 + 491 + // Setting MAGNEMITE ASIC to big endian mode 492 + ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE); 493 + // Download bootloader 494 + card_bootload(dev); 495 + 496 + // Take DSP out of reset 497 + ft1000_write_reg(dev, FT1000_REG_RESET, 0); 498 + // FLARION_DSP_ACTIVE; 499 + mdelay(10); 500 + DEBUG(0, "ft1000_hw:ft1000_reset_card:Take DSP out of reset\n"); 501 + 502 + // Wait for 0xfefe indicating dsp ready before starting download 503 + for (i = 0; i < 50; i++) { 504 + tempword = 505 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, 506 + FT1000_MAG_DPRAM_FEFE_INDX); 507 + if (tempword == 0xfefe) { 508 + break; 509 + } 510 + mdelay(20); 511 + } 512 + 513 + if (i == 50) { 514 + DEBUG(0, 515 + "ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n"); 516 + return FALSE; 517 + } 518 + 519 + } else { 520 + // Take DSP out of reset 521 + ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT); 522 + mdelay(10); 523 + } 524 + 525 + if (card_download(dev, fw_entry->data, fw_entry->size)) { 526 + DEBUG(1, "card download unsuccessful\n"); 527 + return FALSE; 528 + } else { 529 + DEBUG(1, "card download successful\n"); 530 + } 531 + 532 + mdelay(10); 533 + 534 + if (info->AsicID == ELECTRABUZZ_ID) { 535 + // Need to initialize the FIFO length counter to zero in order to sync up 536 + // with the DSP 537 + info->fifo_cnt = 0; 538 + ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt); 539 + // Initialize DSP heartbeat area to ho 540 + ft1000_write_dpram(dev, FT1000_HI_HO, ho); 541 + tempword = ft1000_read_dpram(dev, FT1000_HI_HO); 542 + DEBUG(1, "ft1000_hw:ft1000_reset_asic:hi_ho value = 0x%x\n", 543 + tempword); 544 + } else { 545 + // Initialize DSP heartbeat area to ho 546 + ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag, 547 + FT1000_MAG_HI_HO_INDX); 548 + tempword = 549 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, 550 + FT1000_MAG_HI_HO_INDX); 551 + DEBUG(1, "ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n", 552 + tempword); 553 + } 554 + 555 + info->CardReady = 1; 556 + ft1000_enable_interrupts(dev); 557 + 558 + /* Schedule heartbeat process to run every 2 seconds */ 559 + // poll_timer.expires = jiffies + (2*HZ); 560 + // poll_timer.data = (u_long)dev; 561 + // add_timer(&poll_timer); 562 + 563 + return TRUE; 564 + 565 + } 566 + 567 + //--------------------------------------------------------------------------- 568 + // 569 + // Function: ft1000_chkcard 570 + // Descripton: This function will check if the device is presently available on 571 + // the system. 572 + // Input: 573 + // dev - device structure 574 + // Output: 575 + // status - FALSE (device is not present) 576 + // TRUE (device is present) 577 + // 578 + //--------------------------------------------------------------------------- 579 + static int ft1000_chkcard(struct net_device *dev) 580 + { 581 + u16 tempword; 582 + 583 + // Mask register is used to check for device presence since it is never 584 + // set to zero. 585 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK); 586 + if (tempword == 0) { 587 + DEBUG(1, 588 + "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n"); 589 + return FALSE; 590 + } 591 + // The system will return the value of 0xffff for the version register 592 + // if the device is not present. 593 + tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID); 594 + if (tempword == 0xffff) { 595 + DEBUG(1, 596 + "ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n"); 597 + return FALSE; 598 + } 599 + return TRUE; 600 + } 601 + 602 + 603 + //--------------------------------------------------------------------------- 604 + // 605 + // Function: ft1000_hbchk 606 + // Descripton: This function will perform the heart beat check of the DSP as 607 + // well as the ASIC. 608 + // Input: 609 + // dev - device structure 610 + // Output: 611 + // none 612 + // 613 + //--------------------------------------------------------------------------- 614 + static void ft1000_hbchk(u_long data) 615 + { 616 + struct net_device *dev = (struct net_device *)data; 617 + 618 + FT1000_INFO *info; 619 + USHORT tempword; 620 + 621 + info = (FT1000_INFO *) netdev_priv(dev); 622 + 623 + if (info->CardReady == 1) { 624 + // Perform dsp heartbeat check 625 + if (info->AsicID == ELECTRABUZZ_ID) { 626 + tempword = ft1000_read_dpram(dev, FT1000_HI_HO); 627 + } else { 628 + tempword = 629 + ntohs(ft1000_read_dpram_mag_16 630 + (dev, FT1000_MAG_HI_HO, 631 + FT1000_MAG_HI_HO_INDX)); 632 + } 633 + DEBUG(1, "ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n", 634 + tempword); 635 + // Let's perform another check if ho is not detected 636 + if (tempword != ho) { 637 + if (info->AsicID == ELECTRABUZZ_ID) { 638 + tempword = ft1000_read_dpram(dev, FT1000_HI_HO); 639 + } 640 + else { 641 + tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); 642 + } 643 + } 644 + if (tempword != ho) { 645 + printk(KERN_INFO 646 + "ft1000: heartbeat failed - no ho detected\n"); 647 + if (info->AsicID == ELECTRABUZZ_ID) { 648 + info->DSP_TIME[0] = 649 + ft1000_read_dpram(dev, FT1000_DSP_TIMER0); 650 + info->DSP_TIME[1] = 651 + ft1000_read_dpram(dev, FT1000_DSP_TIMER1); 652 + info->DSP_TIME[2] = 653 + ft1000_read_dpram(dev, FT1000_DSP_TIMER2); 654 + info->DSP_TIME[3] = 655 + ft1000_read_dpram(dev, FT1000_DSP_TIMER3); 656 + } else { 657 + info->DSP_TIME[0] = 658 + ft1000_read_dpram_mag_16(dev, 659 + FT1000_MAG_DSP_TIMER0, 660 + FT1000_MAG_DSP_TIMER0_INDX); 661 + info->DSP_TIME[1] = 662 + ft1000_read_dpram_mag_16(dev, 663 + FT1000_MAG_DSP_TIMER1, 664 + FT1000_MAG_DSP_TIMER1_INDX); 665 + info->DSP_TIME[2] = 666 + ft1000_read_dpram_mag_16(dev, 667 + FT1000_MAG_DSP_TIMER2, 668 + FT1000_MAG_DSP_TIMER2_INDX); 669 + info->DSP_TIME[3] = 670 + ft1000_read_dpram_mag_16(dev, 671 + FT1000_MAG_DSP_TIMER3, 672 + FT1000_MAG_DSP_TIMER3_INDX); 673 + } 674 + info->DrvErrNum = DSP_HB_INFO; 675 + if (ft1000_reset_card(dev) == 0) { 676 + printk(KERN_INFO 677 + "ft1000: Hardware Failure Detected - PC Card disabled\n"); 678 + info->ProgConStat = 0xff; 679 + return; 680 + } 681 + /* Schedule this module to run every 2 seconds */ 682 + poll_timer.expires = jiffies + (2*HZ); 683 + poll_timer.data = (u_long)dev; 684 + add_timer(&poll_timer); 685 + return; 686 + } 687 + 688 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 689 + // Let's check doorbell again if fail 690 + if (tempword & FT1000_DB_HB) { 691 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 692 + } 693 + if (tempword & FT1000_DB_HB) { 694 + printk(KERN_INFO 695 + "ft1000: heartbeat doorbell not clear by firmware\n"); 696 + if (info->AsicID == ELECTRABUZZ_ID) { 697 + info->DSP_TIME[0] = 698 + ft1000_read_dpram(dev, FT1000_DSP_TIMER0); 699 + info->DSP_TIME[1] = 700 + ft1000_read_dpram(dev, FT1000_DSP_TIMER1); 701 + info->DSP_TIME[2] = 702 + ft1000_read_dpram(dev, FT1000_DSP_TIMER2); 703 + info->DSP_TIME[3] = 704 + ft1000_read_dpram(dev, FT1000_DSP_TIMER3); 705 + } else { 706 + info->DSP_TIME[0] = 707 + ft1000_read_dpram_mag_16(dev, 708 + FT1000_MAG_DSP_TIMER0, 709 + FT1000_MAG_DSP_TIMER0_INDX); 710 + info->DSP_TIME[1] = 711 + ft1000_read_dpram_mag_16(dev, 712 + FT1000_MAG_DSP_TIMER1, 713 + FT1000_MAG_DSP_TIMER1_INDX); 714 + info->DSP_TIME[2] = 715 + ft1000_read_dpram_mag_16(dev, 716 + FT1000_MAG_DSP_TIMER2, 717 + FT1000_MAG_DSP_TIMER2_INDX); 718 + info->DSP_TIME[3] = 719 + ft1000_read_dpram_mag_16(dev, 720 + FT1000_MAG_DSP_TIMER3, 721 + FT1000_MAG_DSP_TIMER3_INDX); 722 + } 723 + info->DrvErrNum = DSP_HB_INFO; 724 + if (ft1000_reset_card(dev) == 0) { 725 + printk(KERN_INFO 726 + "ft1000: Hardware Failure Detected - PC Card disabled\n"); 727 + info->ProgConStat = 0xff; 728 + return; 729 + } 730 + /* Schedule this module to run every 2 seconds */ 731 + poll_timer.expires = jiffies + (2*HZ); 732 + poll_timer.data = (u_long)dev; 733 + add_timer(&poll_timer); 734 + return; 735 + } 736 + // Set dedicated area to hi and ring appropriate doorbell according 737 + // to hi/ho heartbeat protocol 738 + if (info->AsicID == ELECTRABUZZ_ID) { 739 + ft1000_write_dpram(dev, FT1000_HI_HO, hi); 740 + } else { 741 + ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, 742 + FT1000_MAG_HI_HO_INDX); 743 + } 744 + 745 + if (info->AsicID == ELECTRABUZZ_ID) { 746 + tempword = ft1000_read_dpram(dev, FT1000_HI_HO); 747 + } else { 748 + tempword = 749 + ntohs(ft1000_read_dpram_mag_16 750 + (dev, FT1000_MAG_HI_HO, 751 + FT1000_MAG_HI_HO_INDX)); 752 + } 753 + // Let's write hi again if fail 754 + if (tempword != hi) { 755 + if (info->AsicID == ELECTRABUZZ_ID) { 756 + ft1000_write_dpram(dev, FT1000_HI_HO, hi); 757 + } 758 + else { 759 + ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX); 760 + } 761 + 762 + if (info->AsicID == ELECTRABUZZ_ID) { 763 + tempword = ft1000_read_dpram(dev, FT1000_HI_HO); 764 + } 765 + else { 766 + tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); 767 + } 768 + 769 + } 770 + 771 + if (tempword != hi) { 772 + printk(KERN_INFO 773 + "ft1000: heartbeat failed - cannot write hi into DPRAM\n"); 774 + if (info->AsicID == ELECTRABUZZ_ID) { 775 + info->DSP_TIME[0] = 776 + ft1000_read_dpram(dev, FT1000_DSP_TIMER0); 777 + info->DSP_TIME[1] = 778 + ft1000_read_dpram(dev, FT1000_DSP_TIMER1); 779 + info->DSP_TIME[2] = 780 + ft1000_read_dpram(dev, FT1000_DSP_TIMER2); 781 + info->DSP_TIME[3] = 782 + ft1000_read_dpram(dev, FT1000_DSP_TIMER3); 783 + } else { 784 + info->DSP_TIME[0] = 785 + ft1000_read_dpram_mag_16(dev, 786 + FT1000_MAG_DSP_TIMER0, 787 + FT1000_MAG_DSP_TIMER0_INDX); 788 + info->DSP_TIME[1] = 789 + ft1000_read_dpram_mag_16(dev, 790 + FT1000_MAG_DSP_TIMER1, 791 + FT1000_MAG_DSP_TIMER1_INDX); 792 + info->DSP_TIME[2] = 793 + ft1000_read_dpram_mag_16(dev, 794 + FT1000_MAG_DSP_TIMER2, 795 + FT1000_MAG_DSP_TIMER2_INDX); 796 + info->DSP_TIME[3] = 797 + ft1000_read_dpram_mag_16(dev, 798 + FT1000_MAG_DSP_TIMER3, 799 + FT1000_MAG_DSP_TIMER3_INDX); 800 + } 801 + info->DrvErrNum = DSP_HB_INFO; 802 + if (ft1000_reset_card(dev) == 0) { 803 + printk(KERN_INFO 804 + "ft1000: Hardware Failure Detected - PC Card disabled\n"); 805 + info->ProgConStat = 0xff; 806 + return; 807 + } 808 + /* Schedule this module to run every 2 seconds */ 809 + poll_timer.expires = jiffies + (2*HZ); 810 + poll_timer.data = (u_long)dev; 811 + add_timer(&poll_timer); 812 + return; 813 + } 814 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB); 815 + 816 + } 817 + 818 + /* Schedule this module to run every 2 seconds */ 819 + poll_timer.expires = jiffies + (2 * HZ); 820 + poll_timer.data = (u_long) dev; 821 + add_timer(&poll_timer); 822 + } 823 + 824 + //--------------------------------------------------------------------------- 825 + // 826 + // Function: ft1000_send_cmd 827 + // Descripton: 828 + // Input: 829 + // Output: 830 + // 831 + //--------------------------------------------------------------------------- 832 + void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype) 833 + { 834 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 835 + int i; 836 + u16 tempword; 837 + unsigned long flags; 838 + 839 + size += PSEUDOSZ; 840 + // check for odd byte and increment to 16-bit word align value 841 + if ((size & 0x0001)) { 842 + size++; 843 + } 844 + DEBUG(1, "FT1000:ft1000_send_cmd:total length = %d\n", size); 845 + DEBUG(1, "FT1000:ft1000_send_cmd:length = %d\n", ntohs(*ptempbuffer)); 846 + // put message into slow queue area 847 + // All messages are in the form total_len + pseudo header + message body 848 + spin_lock_irqsave(&info->dpram_lock, flags); 849 + 850 + // Make sure SLOWQ doorbell is clear 851 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 852 + i=0; 853 + while (tempword & FT1000_DB_DPRAM_TX) { 854 + mdelay(10); 855 + i++; 856 + if (i==10) { 857 + spin_unlock_irqrestore(&info->dpram_lock, flags); 858 + return; 859 + } 860 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 861 + } 862 + 863 + if (info->AsicID == ELECTRABUZZ_ID) { 864 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 865 + FT1000_DPRAM_TX_BASE); 866 + // Write total length to dpram 867 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size); 868 + // Write pseudo header and messgae body 869 + for (i = 0; i < (size >> 1); i++) { 870 + DEBUG(1, "FT1000:ft1000_send_cmd:data %d = 0x%x\n", i, 871 + *ptempbuffer); 872 + tempword = htons(*ptempbuffer++); 873 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword); 874 + } 875 + } else { 876 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 877 + FT1000_DPRAM_MAG_TX_BASE); 878 + // Write total length to dpram 879 + ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size)); 880 + // Write pseudo header and messgae body 881 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 882 + FT1000_DPRAM_MAG_TX_BASE + 1); 883 + for (i = 0; i < (size >> 2); i++) { 884 + DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", 885 + *ptempbuffer); 886 + outw(*ptempbuffer++, 887 + dev->base_addr + FT1000_REG_MAG_DPDATAL); 888 + DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", 889 + *ptempbuffer); 890 + outw(*ptempbuffer++, 891 + dev->base_addr + FT1000_REG_MAG_DPDATAH); 892 + } 893 + DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer); 894 + outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL); 895 + DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer); 896 + outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH); 897 + } 898 + spin_unlock_irqrestore(&info->dpram_lock, flags); 899 + 900 + // ring doorbell to notify DSP that we have a message ready 901 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX); 902 + } 903 + 904 + //--------------------------------------------------------------------------- 905 + // 906 + // Function: ft1000_receive_cmd 907 + // Descripton: This function will read a message from the dpram area. 908 + // Input: 909 + // dev - network device structure 910 + // pbuffer - caller supply address to buffer 911 + // pnxtph - pointer to next pseudo header 912 + // Output: 913 + // Status = 0 (unsuccessful) 914 + // = 1 (successful) 915 + // 916 + //--------------------------------------------------------------------------- 917 + BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph) 918 + { 919 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 920 + u16 size; 921 + u16 *ppseudohdr; 922 + int i; 923 + u16 tempword; 924 + unsigned long flags; 925 + 926 + if (info->AsicID == ELECTRABUZZ_ID) { 927 + size = ( ft1000_read_dpram(dev, *pnxtph) ) + PSEUDOSZ; 928 + } else { 929 + size = 930 + ntohs(ft1000_read_dpram_mag_16 931 + (dev, FT1000_MAG_PH_LEN, 932 + FT1000_MAG_PH_LEN_INDX)) + PSEUDOSZ; 933 + } 934 + if (size > maxsz) { 935 + DEBUG(1, 936 + "FT1000:ft1000_receive_cmd:Invalid command length = %d\n", 937 + size); 938 + return FALSE; 939 + } else { 940 + ppseudohdr = (u16 *) pbuffer; 941 + spin_lock_irqsave(&info->dpram_lock, flags); 942 + if (info->AsicID == ELECTRABUZZ_ID) { 943 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 944 + FT1000_DPRAM_RX_BASE + 2); 945 + for (i = 0; i <= (size >> 1); i++) { 946 + tempword = 947 + ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 948 + *pbuffer++ = ntohs(tempword); 949 + } 950 + } else { 951 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 952 + FT1000_DPRAM_MAG_RX_BASE); 953 + *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH); 954 + DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer); 955 + pbuffer++; 956 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 957 + FT1000_DPRAM_MAG_RX_BASE + 1); 958 + for (i = 0; i <= (size >> 2); i++) { 959 + *pbuffer = 960 + inw(dev->base_addr + 961 + FT1000_REG_MAG_DPDATAL); 962 + pbuffer++; 963 + *pbuffer = 964 + inw(dev->base_addr + 965 + FT1000_REG_MAG_DPDATAH); 966 + pbuffer++; 967 + } 968 + //copy odd aligned word 969 + *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL); 970 + DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer); 971 + pbuffer++; 972 + *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH); 973 + DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer); 974 + pbuffer++; 975 + } 976 + if (size & 0x0001) { 977 + //copy odd byte from fifo 978 + tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); 979 + *pbuffer = ntohs(tempword); 980 + } 981 + spin_unlock_irqrestore(&info->dpram_lock, flags); 982 + 983 + // Check if pseudo header checksum is good 984 + // Calculate pseudo header checksum 985 + tempword = *ppseudohdr++; 986 + for (i = 1; i < 7; i++) { 987 + tempword ^= *ppseudohdr++; 988 + } 989 + if ((tempword != *ppseudohdr)) { 990 + DEBUG(1, 991 + "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n"); 992 + // Drop this message 993 + return FALSE; 994 + } 995 + return TRUE; 996 + } 997 + } 998 + 999 + //--------------------------------------------------------------------------- 1000 + // 1001 + // Function: ft1000_proc_drvmsg 1002 + // Descripton: This function will process the various driver messages. 1003 + // Input: 1004 + // dev - device structure 1005 + // pnxtph - pointer to next pseudo header 1006 + // Output: 1007 + // none 1008 + // 1009 + //--------------------------------------------------------------------------- 1010 + void ft1000_proc_drvmsg(struct net_device *dev) 1011 + { 1012 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1013 + u16 msgtype; 1014 + u16 tempword; 1015 + PMEDIAMSG pmediamsg; 1016 + PDSPINITMSG pdspinitmsg; 1017 + PDRVMSG pdrvmsg; 1018 + u16 len; 1019 + u16 i; 1020 + PPROV_RECORD ptr; 1021 + PPSEUDO_HDR ppseudo_hdr; 1022 + PUSHORT pmsg; 1023 + struct timeval tv; 1024 + union { 1025 + u8 byte[2]; 1026 + u16 wrd; 1027 + } convert; 1028 + 1029 + if (info->AsicID == ELECTRABUZZ_ID) { 1030 + tempword = FT1000_DPRAM_RX_BASE+2; 1031 + } 1032 + else { 1033 + tempword = FT1000_DPRAM_MAG_RX_BASE; 1034 + } 1035 + if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) { 1036 + 1037 + // Get the message type which is total_len + PSEUDO header + msgtype + message body 1038 + pdrvmsg = (PDRVMSG) & cmdbuffer[0]; 1039 + msgtype = ntohs(pdrvmsg->type); 1040 + DEBUG(1, "Command message type = 0x%x\n", msgtype); 1041 + switch (msgtype) { 1042 + case DSP_PROVISION: 1043 + DEBUG(0, 1044 + "Got a provisioning request message from DSP\n"); 1045 + mdelay(25); 1046 + while (list_empty(&info->prov_list) == 0) { 1047 + DEBUG(0, "Sending a provisioning message\n"); 1048 + // Make sure SLOWQ doorbell is clear 1049 + tempword = 1050 + ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1051 + i = 0; 1052 + while (tempword & FT1000_DB_DPRAM_TX) { 1053 + mdelay(5); 1054 + i++; 1055 + if (i == 10) { 1056 + break; 1057 + } 1058 + } 1059 + ptr = 1060 + list_entry(info->prov_list.next, 1061 + PROV_RECORD, list); 1062 + len = *(u16 *) ptr->pprov_data; 1063 + len = htons(len); 1064 + 1065 + pmsg = (PUSHORT) ptr->pprov_data; 1066 + ppseudo_hdr = (PPSEUDO_HDR) pmsg; 1067 + // Insert slow queue sequence number 1068 + ppseudo_hdr->seq_num = info->squeseqnum++; 1069 + ppseudo_hdr->portsrc = 0; 1070 + // Calculate new checksum 1071 + ppseudo_hdr->checksum = *pmsg++; 1072 + DEBUG(1, "checksum = 0x%x\n", 1073 + ppseudo_hdr->checksum); 1074 + for (i = 1; i < 7; i++) { 1075 + ppseudo_hdr->checksum ^= *pmsg++; 1076 + DEBUG(1, "checksum = 0x%x\n", 1077 + ppseudo_hdr->checksum); 1078 + } 1079 + 1080 + ft1000_send_cmd (dev, (u16 *)ptr->pprov_data, len, SLOWQ_TYPE); 1081 + list_del(&ptr->list); 1082 + kfree(ptr->pprov_data); 1083 + kfree(ptr); 1084 + } 1085 + // Indicate adapter is ready to take application messages after all 1086 + // provisioning messages are sent 1087 + info->CardReady = 1; 1088 + break; 1089 + case MEDIA_STATE: 1090 + pmediamsg = (PMEDIAMSG) & cmdbuffer[0]; 1091 + if (info->ProgConStat != 0xFF) { 1092 + if (pmediamsg->state) { 1093 + DEBUG(1, "Media is up\n"); 1094 + if (info->mediastate == 0) { 1095 + netif_carrier_on(dev); 1096 + netif_wake_queue(dev); 1097 + info->mediastate = 1; 1098 + do_gettimeofday(&tv); 1099 + info->ConTm = tv.tv_sec; 1100 + } 1101 + } else { 1102 + DEBUG(1, "Media is down\n"); 1103 + if (info->mediastate == 1) { 1104 + info->mediastate = 0; 1105 + netif_carrier_off(dev); 1106 + netif_stop_queue(dev); 1107 + info->ConTm = 0; 1108 + } 1109 + } 1110 + } 1111 + else { 1112 + DEBUG(1,"Media is down\n"); 1113 + if (info->mediastate == 1) { 1114 + info->mediastate = 0; 1115 + netif_carrier_off(dev); 1116 + netif_stop_queue(dev); 1117 + info->ConTm = 0; 1118 + } 1119 + } 1120 + break; 1121 + case DSP_INIT_MSG: 1122 + pdspinitmsg = (PDSPINITMSG) & cmdbuffer[0]; 1123 + memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ); 1124 + DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n", 1125 + info->DspVer[0], info->DspVer[1], info->DspVer[2], 1126 + info->DspVer[3]); 1127 + memcpy(info->HwSerNum, pdspinitmsg->HwSerNum, 1128 + HWSERNUMSZ); 1129 + memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ); 1130 + memcpy(info->eui64, pdspinitmsg->eui64, EUISZ); 1131 + dev->dev_addr[0] = info->eui64[0]; 1132 + dev->dev_addr[1] = info->eui64[1]; 1133 + dev->dev_addr[2] = info->eui64[2]; 1134 + dev->dev_addr[3] = info->eui64[5]; 1135 + dev->dev_addr[4] = info->eui64[6]; 1136 + dev->dev_addr[5] = info->eui64[7]; 1137 + 1138 + if (ntohs(pdspinitmsg->length) == 1139 + (sizeof(DSPINITMSG) - 20)) { 1140 + memcpy(info->ProductMode, 1141 + pdspinitmsg->ProductMode, MODESZ); 1142 + memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, 1143 + CALVERSZ); 1144 + memcpy(info->RfCalDate, pdspinitmsg->RfCalDate, 1145 + CALDATESZ); 1146 + DEBUG(1, "RFCalVer = 0x%2x 0x%2x\n", 1147 + info->RfCalVer[0], info->RfCalVer[1]); 1148 + } 1149 + 1150 + break ; 1151 + case DSP_STORE_INFO: 1152 + DEBUG(1, "FT1000:drivermsg:Got DSP_STORE_INFO\n"); 1153 + tempword = ntohs(pdrvmsg->length); 1154 + info->DSPInfoBlklen = tempword; 1155 + if (tempword < (MAX_DSP_SESS_REC - 4)) { 1156 + pmsg = (PUSHORT) & pdrvmsg->data[0]; 1157 + for (i = 0; i < ((tempword + 1) / 2); i++) { 1158 + DEBUG(1, 1159 + "FT1000:drivermsg:dsp info data = 0x%x\n", 1160 + *pmsg); 1161 + info->DSPInfoBlk[i + 10] = *pmsg++; 1162 + } 1163 + } 1164 + break; 1165 + case DSP_GET_INFO: 1166 + DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n"); 1167 + // copy dsp info block to dsp 1168 + info->DrvMsgPend = 1; 1169 + // allow any outstanding ioctl to finish 1170 + mdelay(10); 1171 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1172 + if (tempword & FT1000_DB_DPRAM_TX) { 1173 + mdelay(10); 1174 + tempword = 1175 + ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1176 + if (tempword & FT1000_DB_DPRAM_TX) { 1177 + mdelay(10); 1178 + } 1179 + } 1180 + 1181 + if ((tempword & FT1000_DB_DPRAM_TX) == 0) { 1182 + // Put message into Slow Queue 1183 + // Form Pseudo header 1184 + pmsg = (PUSHORT) info->DSPInfoBlk; 1185 + ppseudo_hdr = (PPSEUDO_HDR) pmsg; 1186 + ppseudo_hdr->length = 1187 + htons(info->DSPInfoBlklen + 4); 1188 + ppseudo_hdr->source = 0x10; 1189 + ppseudo_hdr->destination = 0x20; 1190 + ppseudo_hdr->portdest = 0; 1191 + ppseudo_hdr->portsrc = 0; 1192 + ppseudo_hdr->sh_str_id = 0; 1193 + ppseudo_hdr->control = 0; 1194 + ppseudo_hdr->rsvd1 = 0; 1195 + ppseudo_hdr->rsvd2 = 0; 1196 + ppseudo_hdr->qos_class = 0; 1197 + // Insert slow queue sequence number 1198 + ppseudo_hdr->seq_num = info->squeseqnum++; 1199 + // Insert application id 1200 + ppseudo_hdr->portsrc = 0; 1201 + // Calculate new checksum 1202 + ppseudo_hdr->checksum = *pmsg++; 1203 + for (i = 1; i < 7; i++) { 1204 + ppseudo_hdr->checksum ^= *pmsg++; 1205 + } 1206 + info->DSPInfoBlk[8] = 0x7200; 1207 + info->DSPInfoBlk[9] = 1208 + htons(info->DSPInfoBlklen); 1209 + ft1000_send_cmd (dev, (PUSHORT)info->DSPInfoBlk, (USHORT)(info->DSPInfoBlklen+4), 0); 1210 + } 1211 + info->DrvMsgPend = 0; 1212 + 1213 + break; 1214 + case GET_DRV_ERR_RPT_MSG: 1215 + DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n"); 1216 + // copy driver error message to dsp 1217 + info->DrvMsgPend = 1; 1218 + // allow any outstanding ioctl to finish 1219 + mdelay(10); 1220 + tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1221 + if (tempword & FT1000_DB_DPRAM_TX) { 1222 + mdelay(10); 1223 + tempword = 1224 + ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1225 + if (tempword & FT1000_DB_DPRAM_TX) { 1226 + mdelay(10); 1227 + } 1228 + } 1229 + 1230 + if ((tempword & FT1000_DB_DPRAM_TX) == 0) { 1231 + // Put message into Slow Queue 1232 + // Form Pseudo header 1233 + pmsg = (PUSHORT) & tempbuffer[0]; 1234 + ppseudo_hdr = (PPSEUDO_HDR) pmsg; 1235 + ppseudo_hdr->length = htons(0x0012); 1236 + ppseudo_hdr->source = 0x10; 1237 + ppseudo_hdr->destination = 0x20; 1238 + ppseudo_hdr->portdest = 0; 1239 + ppseudo_hdr->portsrc = 0; 1240 + ppseudo_hdr->sh_str_id = 0; 1241 + ppseudo_hdr->control = 0; 1242 + ppseudo_hdr->rsvd1 = 0; 1243 + ppseudo_hdr->rsvd2 = 0; 1244 + ppseudo_hdr->qos_class = 0; 1245 + // Insert slow queue sequence number 1246 + ppseudo_hdr->seq_num = info->squeseqnum++; 1247 + // Insert application id 1248 + ppseudo_hdr->portsrc = 0; 1249 + // Calculate new checksum 1250 + ppseudo_hdr->checksum = *pmsg++; 1251 + for (i=1; i<7; i++) { 1252 + ppseudo_hdr->checksum ^= *pmsg++; 1253 + } 1254 + pmsg = (PUSHORT) & tempbuffer[16]; 1255 + *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); 1256 + *pmsg++ = htons(0x000e); 1257 + *pmsg++ = htons(info->DSP_TIME[0]); 1258 + *pmsg++ = htons(info->DSP_TIME[1]); 1259 + *pmsg++ = htons(info->DSP_TIME[2]); 1260 + *pmsg++ = htons(info->DSP_TIME[3]); 1261 + convert.byte[0] = info->DspVer[0]; 1262 + convert.byte[1] = info->DspVer[1]; 1263 + *pmsg++ = convert.wrd; 1264 + convert.byte[0] = info->DspVer[2]; 1265 + convert.byte[1] = info->DspVer[3]; 1266 + *pmsg++ = convert.wrd; 1267 + *pmsg++ = htons(info->DrvErrNum); 1268 + 1269 + ft1000_send_cmd (dev, (PUSHORT)&tempbuffer[0], (USHORT)(0x0012), 0); 1270 + info->DrvErrNum = 0; 1271 + } 1272 + info->DrvMsgPend = 0; 1273 + 1274 + break; 1275 + default: 1276 + break; 1277 + } 1278 + } 1279 + } 1280 + 1281 + //--------------------------------------------------------------------------- 1282 + // 1283 + // Function: ft1000_parse_dpram_msg 1284 + // Descripton: This function will parse the message received from the DSP 1285 + // via the DPRAM interface. 1286 + // Input: 1287 + // dev - device structure 1288 + // Output: 1289 + // status - FAILURE 1290 + // SUCCESS 1291 + // 1292 + //--------------------------------------------------------------------------- 1293 + int ft1000_parse_dpram_msg(struct net_device *dev) 1294 + { 1295 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1296 + u16 doorbell; 1297 + u16 portid; 1298 + u16 nxtph; 1299 + u16 total_len; 1300 + int i = 0; 1301 + int cnt; 1302 + unsigned long flags; 1303 + 1304 + doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL); 1305 + DEBUG(1, "Doorbell = 0x%x\n", doorbell); 1306 + 1307 + if (doorbell & FT1000_ASIC_RESET_REQ) { 1308 + // Copy DSP session record from info block 1309 + spin_lock_irqsave(&info->dpram_lock, flags); 1310 + if (info->AsicID == ELECTRABUZZ_ID) { 1311 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 1312 + FT1000_DPRAM_RX_BASE); 1313 + for (i = 0; i < MAX_DSP_SESS_REC; i++) { 1314 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, 1315 + info->DSPSess.Rec[i]); 1316 + } 1317 + } else { 1318 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, 1319 + FT1000_DPRAM_MAG_RX_BASE); 1320 + for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) { 1321 + outl(info->DSPSess.MagRec[i], 1322 + dev->base_addr + FT1000_REG_MAG_DPDATA); 1323 + } 1324 + } 1325 + spin_unlock_irqrestore(&info->dpram_lock, flags); 1326 + 1327 + // clear ASIC RESET request 1328 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, 1329 + FT1000_ASIC_RESET_REQ); 1330 + DEBUG(1, "Got an ASIC RESET Request\n"); 1331 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, 1332 + FT1000_ASIC_RESET_DSP); 1333 + 1334 + if (info->AsicID == MAGNEMITE_ID) { 1335 + // Setting MAGNEMITE ASIC to big endian mode 1336 + ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, 1337 + HOST_INTF_BE); 1338 + } 1339 + info->DspAsicReset = 0; 1340 + } 1341 + 1342 + if (doorbell & FT1000_DSP_ASIC_RESET) { 1343 + DEBUG(0, 1344 + "FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n"); 1345 + info->DspAsicReset = 1; 1346 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, 1347 + FT1000_DSP_ASIC_RESET); 1348 + udelay(200); 1349 + return SUCCESS; 1350 + } 1351 + 1352 + if (doorbell & FT1000_DB_DPRAM_RX) { 1353 + DEBUG(1, 1354 + "FT1000:ft1000_parse_dpram_msg: Got a slow queue message\n"); 1355 + nxtph = FT1000_DPRAM_RX_BASE + 2; 1356 + if (info->AsicID == ELECTRABUZZ_ID) { 1357 + total_len = 1358 + ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE); 1359 + } else { 1360 + total_len = 1361 + ntohs(ft1000_read_dpram_mag_16 1362 + (dev, FT1000_MAG_TOTAL_LEN, 1363 + FT1000_MAG_TOTAL_LEN_INDX)); 1364 + } 1365 + DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n", 1366 + total_len); 1367 + if ((total_len < MAX_CMD_SQSIZE) && (total_len > PSEUDOSZ)) { 1368 + total_len += nxtph; 1369 + cnt = 0; 1370 + // ft1000_read_reg will return a value that needs to be byteswap 1371 + // in order to get DSP_QID_OFFSET. 1372 + if (info->AsicID == ELECTRABUZZ_ID) { 1373 + portid = 1374 + (ft1000_read_dpram 1375 + (dev, 1376 + DSP_QID_OFFSET + FT1000_DPRAM_RX_BASE + 1377 + 2) >> 8) & 0xff; 1378 + } else { 1379 + portid = 1380 + (ft1000_read_dpram_mag_16 1381 + (dev, FT1000_MAG_PORT_ID, 1382 + FT1000_MAG_PORT_ID_INDX) & 0xff); 1383 + } 1384 + DEBUG(1, "DSP_QID = 0x%x\n", portid); 1385 + 1386 + if (portid == DRIVERID) { 1387 + // We are assumming one driver message from the DSP at a time. 1388 + ft1000_proc_drvmsg(dev); 1389 + } 1390 + } 1391 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX); 1392 + } 1393 + 1394 + if (doorbell & FT1000_DB_COND_RESET) { 1395 + // Reset ASIC and DSP 1396 + if (info->AsicID == ELECTRABUZZ_ID) { 1397 + info->DSP_TIME[0] = 1398 + ft1000_read_dpram(dev, FT1000_DSP_TIMER0); 1399 + info->DSP_TIME[1] = 1400 + ft1000_read_dpram(dev, FT1000_DSP_TIMER1); 1401 + info->DSP_TIME[2] = 1402 + ft1000_read_dpram(dev, FT1000_DSP_TIMER2); 1403 + info->DSP_TIME[3] = 1404 + ft1000_read_dpram(dev, FT1000_DSP_TIMER3); 1405 + } else { 1406 + info->DSP_TIME[0] = 1407 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0, 1408 + FT1000_MAG_DSP_TIMER0_INDX); 1409 + info->DSP_TIME[1] = 1410 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1, 1411 + FT1000_MAG_DSP_TIMER1_INDX); 1412 + info->DSP_TIME[2] = 1413 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2, 1414 + FT1000_MAG_DSP_TIMER2_INDX); 1415 + info->DSP_TIME[3] = 1416 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3, 1417 + FT1000_MAG_DSP_TIMER3_INDX); 1418 + } 1419 + info->DrvErrNum = DSP_CONDRESET_INFO; 1420 + DEBUG(1, "ft1000_hw:DSP conditional reset requested\n"); 1421 + ft1000_reset_card(dev); 1422 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, 1423 + FT1000_DB_COND_RESET); 1424 + } 1425 + // let's clear any unexpected doorbells from DSP 1426 + doorbell = 1427 + doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ | 1428 + FT1000_DB_COND_RESET | 0xff00); 1429 + if (doorbell) { 1430 + DEBUG(1, "Clearing unexpected doorbell = 0x%x\n", doorbell); 1431 + ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell); 1432 + } 1433 + 1434 + return SUCCESS; 1435 + 1436 + } 1437 + 1438 + //--------------------------------------------------------------------------- 1439 + // 1440 + // Function: ft1000_flush_fifo 1441 + // Descripton: This function will flush one packet from the downlink 1442 + // FIFO. 1443 + // Input: 1444 + // dev - device structure 1445 + // drv_err - driver error causing the flush fifo 1446 + // Output: 1447 + // None. 1448 + // 1449 + //--------------------------------------------------------------------------- 1450 + static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) 1451 + { 1452 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1453 + u16 i; 1454 + u32 templong; 1455 + u16 tempword; 1456 + 1457 + DEBUG(1, "ft1000:ft1000_hw:ft1000_flush_fifo called\n"); 1458 + if (info->PktIntfErr > MAX_PH_ERR) { 1459 + if (info->AsicID == ELECTRABUZZ_ID) { 1460 + info->DSP_TIME[0] = 1461 + ft1000_read_dpram(dev, FT1000_DSP_TIMER0); 1462 + info->DSP_TIME[1] = 1463 + ft1000_read_dpram(dev, FT1000_DSP_TIMER1); 1464 + info->DSP_TIME[2] = 1465 + ft1000_read_dpram(dev, FT1000_DSP_TIMER2); 1466 + info->DSP_TIME[3] = 1467 + ft1000_read_dpram(dev, FT1000_DSP_TIMER3); 1468 + } else { 1469 + info->DSP_TIME[0] = 1470 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0, 1471 + FT1000_MAG_DSP_TIMER0_INDX); 1472 + info->DSP_TIME[1] = 1473 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1, 1474 + FT1000_MAG_DSP_TIMER1_INDX); 1475 + info->DSP_TIME[2] = 1476 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2, 1477 + FT1000_MAG_DSP_TIMER2_INDX); 1478 + info->DSP_TIME[3] = 1479 + ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3, 1480 + FT1000_MAG_DSP_TIMER3_INDX); 1481 + } 1482 + info->DrvErrNum = DrvErrNum; 1483 + ft1000_reset_card(dev); 1484 + return; 1485 + } else { 1486 + // Flush corrupted pkt from FIFO 1487 + i = 0; 1488 + do { 1489 + if (info->AsicID == ELECTRABUZZ_ID) { 1490 + tempword = 1491 + ft1000_read_reg(dev, FT1000_REG_DFIFO); 1492 + tempword = 1493 + ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT); 1494 + } else { 1495 + templong = 1496 + inl(dev->base_addr + FT1000_REG_MAG_DFR); 1497 + tempword = 1498 + inw(dev->base_addr + FT1000_REG_MAG_DFSR); 1499 + } 1500 + i++; 1501 + // This should never happen unless the ASIC is broken. 1502 + // We must reset to recover. 1503 + if ((i > 2048) || (tempword == 0)) { 1504 + if (info->AsicID == ELECTRABUZZ_ID) { 1505 + info->DSP_TIME[0] = 1506 + ft1000_read_dpram(dev, 1507 + FT1000_DSP_TIMER0); 1508 + info->DSP_TIME[1] = 1509 + ft1000_read_dpram(dev, 1510 + FT1000_DSP_TIMER1); 1511 + info->DSP_TIME[2] = 1512 + ft1000_read_dpram(dev, 1513 + FT1000_DSP_TIMER2); 1514 + info->DSP_TIME[3] = 1515 + ft1000_read_dpram(dev, 1516 + FT1000_DSP_TIMER3); 1517 + } else { 1518 + info->DSP_TIME[0] = 1519 + ft1000_read_dpram_mag_16(dev, 1520 + FT1000_MAG_DSP_TIMER0, 1521 + FT1000_MAG_DSP_TIMER0_INDX); 1522 + info->DSP_TIME[1] = 1523 + ft1000_read_dpram_mag_16(dev, 1524 + FT1000_MAG_DSP_TIMER1, 1525 + FT1000_MAG_DSP_TIMER1_INDX); 1526 + info->DSP_TIME[2] = 1527 + ft1000_read_dpram_mag_16(dev, 1528 + FT1000_MAG_DSP_TIMER2, 1529 + FT1000_MAG_DSP_TIMER2_INDX); 1530 + info->DSP_TIME[3] = 1531 + ft1000_read_dpram_mag_16(dev, 1532 + FT1000_MAG_DSP_TIMER3, 1533 + FT1000_MAG_DSP_TIMER3_INDX); 1534 + } 1535 + if (tempword == 0) { 1536 + // Let's check if ASIC reads are still ok by reading the Mask register 1537 + // which is never zero at this point of the code. 1538 + tempword = 1539 + inw(dev->base_addr + 1540 + FT1000_REG_SUP_IMASK); 1541 + if (tempword == 0) { 1542 + // This indicates that we can not communicate with the ASIC 1543 + info->DrvErrNum = 1544 + FIFO_FLUSH_BADCNT; 1545 + } else { 1546 + // Let's assume that we really flush the FIFO 1547 + info->PktIntfErr++; 1548 + return; 1549 + } 1550 + } else { 1551 + info->DrvErrNum = FIFO_FLUSH_MAXLIMIT; 1552 + } 1553 + return; 1554 + } 1555 + tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT); 1556 + } while ((tempword & 0x03) != 0x03); 1557 + if (info->AsicID == ELECTRABUZZ_ID) { 1558 + i++; 1559 + DEBUG(0, "Flushing FIFO complete = %x\n", tempword); 1560 + // Flush last word in FIFO. 1561 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1562 + // Update FIFO counter for DSP 1563 + i = i * 2; 1564 + DEBUG(0, "Flush Data byte count to dsp = %d\n", i); 1565 + info->fifo_cnt += i; 1566 + ft1000_write_dpram(dev, FT1000_FIFO_LEN, 1567 + info->fifo_cnt); 1568 + } else { 1569 + DEBUG(0, "Flushing FIFO complete = %x\n", tempword); 1570 + // Flush last word in FIFO 1571 + templong = inl(dev->base_addr + FT1000_REG_MAG_DFR); 1572 + tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT); 1573 + DEBUG(0, "FT1000_REG_SUP_STAT = 0x%x\n", tempword); 1574 + tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR); 1575 + DEBUG(0, "FT1000_REG_MAG_DFSR = 0x%x\n", tempword); 1576 + } 1577 + if (DrvErrNum) { 1578 + info->PktIntfErr++; 1579 + } 1580 + } 1581 + } 1582 + 1583 + //--------------------------------------------------------------------------- 1584 + // 1585 + // Function: ft1000_copy_up_pkt 1586 + // Descripton: This function will pull Flarion packets out of the Downlink 1587 + // FIFO and convert it to an ethernet packet. The ethernet packet will 1588 + // then be deliver to the TCP/IP stack. 1589 + // Input: 1590 + // dev - device structure 1591 + // Output: 1592 + // status - FAILURE 1593 + // SUCCESS 1594 + // 1595 + //--------------------------------------------------------------------------- 1596 + int ft1000_copy_up_pkt(struct net_device *dev) 1597 + { 1598 + u16 tempword; 1599 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1600 + u16 len; 1601 + struct sk_buff *skb; 1602 + u16 i; 1603 + u8 *pbuffer = NULL; 1604 + u8 *ptemp = NULL; 1605 + u16 chksum; 1606 + u32 *ptemplong; 1607 + u32 templong; 1608 + 1609 + DEBUG(1, "ft1000_copy_up_pkt\n"); 1610 + // Read length 1611 + if (info->AsicID == ELECTRABUZZ_ID) { 1612 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1613 + len = tempword; 1614 + } else { 1615 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL); 1616 + len = ntohs(tempword); 1617 + } 1618 + chksum = tempword; 1619 + DEBUG(1, "Number of Bytes in FIFO = %d\n", len); 1620 + 1621 + if (len > ENET_MAX_SIZE) { 1622 + DEBUG(0, "size of ethernet packet invalid\n"); 1623 + if (info->AsicID == MAGNEMITE_ID) { 1624 + // Read High word to complete 32 bit access 1625 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1626 + } 1627 + ft1000_flush_fifo(dev, DSP_PKTLEN_INFO); 1628 + info->stats.rx_errors++; 1629 + return FAILURE; 1630 + } 1631 + 1632 + skb = dev_alloc_skb(len + 12 + 2); 1633 + 1634 + if (skb == NULL) { 1635 + DEBUG(0, "No Network buffers available\n"); 1636 + // Read High word to complete 32 bit access 1637 + if (info->AsicID == MAGNEMITE_ID) { 1638 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1639 + } 1640 + ft1000_flush_fifo(dev, 0); 1641 + info->stats.rx_errors++; 1642 + return FAILURE; 1643 + } 1644 + pbuffer = (u8 *) skb_put(skb, len + 12); 1645 + 1646 + // Pseudo header 1647 + if (info->AsicID == ELECTRABUZZ_ID) { 1648 + for (i = 1; i < 7; i++) { 1649 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1650 + chksum ^= tempword; 1651 + } 1652 + // read checksum value 1653 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1654 + } else { 1655 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1656 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1657 + chksum ^= tempword; 1658 + 1659 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL); 1660 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1661 + chksum ^= tempword; 1662 + 1663 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1664 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1665 + chksum ^= tempword; 1666 + 1667 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL); 1668 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1669 + chksum ^= tempword; 1670 + 1671 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1672 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1673 + chksum ^= tempword; 1674 + 1675 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL); 1676 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1677 + chksum ^= tempword; 1678 + 1679 + // read checksum value 1680 + tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); 1681 + DEBUG(1, "Pseudo = 0x%x\n", tempword); 1682 + } 1683 + 1684 + if (chksum != tempword) { 1685 + DEBUG(0, "Packet checksum mismatch 0x%x 0x%x\n", chksum, 1686 + tempword); 1687 + ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO); 1688 + info->stats.rx_errors++; 1689 + return FAILURE; 1690 + } 1691 + //subtract the number of bytes read already 1692 + ptemp = pbuffer; 1693 + 1694 + // fake MAC address 1695 + *pbuffer++ = dev->dev_addr[0]; 1696 + *pbuffer++ = dev->dev_addr[1]; 1697 + *pbuffer++ = dev->dev_addr[2]; 1698 + *pbuffer++ = dev->dev_addr[3]; 1699 + *pbuffer++ = dev->dev_addr[4]; 1700 + *pbuffer++ = dev->dev_addr[5]; 1701 + *pbuffer++ = 0x00; 1702 + *pbuffer++ = 0x07; 1703 + *pbuffer++ = 0x35; 1704 + *pbuffer++ = 0xff; 1705 + *pbuffer++ = 0xff; 1706 + *pbuffer++ = 0xfe; 1707 + 1708 + if (info->AsicID == ELECTRABUZZ_ID) { 1709 + for (i = 0; i < len / 2; i++) { 1710 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1711 + *pbuffer++ = (u8) (tempword >> 8); 1712 + *pbuffer++ = (u8) tempword; 1713 + if (ft1000_chkcard(dev) == FALSE) { 1714 + return FAILURE; 1715 + } 1716 + } 1717 + 1718 + // Need to read one more word if odd byte 1719 + if (len & 0x0001) { 1720 + tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); 1721 + *pbuffer++ = (u8) (tempword >> 8); 1722 + } 1723 + } else { 1724 + ptemplong = (u32 *) pbuffer; 1725 + for (i = 0; i < len / 4; i++) { 1726 + templong = inl(dev->base_addr + FT1000_REG_MAG_DFR); 1727 + DEBUG(1, "Data = 0x%8x\n", templong); 1728 + *ptemplong++ = templong; 1729 + } 1730 + 1731 + // Need to read one more word if odd align. 1732 + if (len & 0x0003) { 1733 + templong = inl(dev->base_addr + FT1000_REG_MAG_DFR); 1734 + DEBUG(1, "Data = 0x%8x\n", templong); 1735 + *ptemplong++ = templong; 1736 + } 1737 + 1738 + } 1739 + 1740 + DEBUG(1, "Data passed to Protocol layer:\n"); 1741 + for (i = 0; i < len + 12; i++) { 1742 + DEBUG(1, "Protocol Data: 0x%x\n ", *ptemp++); 1743 + } 1744 + 1745 + skb->dev = dev; 1746 + skb->protocol = eth_type_trans(skb, dev); 1747 + skb->ip_summed = CHECKSUM_UNNECESSARY; 1748 + netif_rx(skb); 1749 + 1750 + info->stats.rx_packets++; 1751 + // Add on 12 bytes for MAC address which was removed 1752 + info->stats.rx_bytes += (len + 12); 1753 + 1754 + if (info->AsicID == ELECTRABUZZ_ID) { 1755 + // track how many bytes have been read from FIFO - round up to 16 bit word 1756 + tempword = len + 16; 1757 + if (tempword & 0x01) 1758 + tempword++; 1759 + info->fifo_cnt += tempword; 1760 + ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN); 1761 + ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt); 1762 + } 1763 + 1764 + return SUCCESS; 1765 + } 1766 + 1767 + //--------------------------------------------------------------------------- 1768 + // 1769 + // Function: ft1000_copy_down_pkt 1770 + // Descripton: This function will take an ethernet packet and convert it to 1771 + // a Flarion packet prior to sending it to the ASIC Downlink 1772 + // FIFO. 1773 + // Input: 1774 + // dev - device structure 1775 + // packet - address of ethernet packet 1776 + // len - length of IP packet 1777 + // Output: 1778 + // status - FAILURE 1779 + // SUCCESS 1780 + // 1781 + //--------------------------------------------------------------------------- 1782 + int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) 1783 + { 1784 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1785 + union { 1786 + PSEUDO_HDR blk; 1787 + u16 buff[sizeof(PSEUDO_HDR) >> 1]; 1788 + u8 buffc[sizeof(PSEUDO_HDR)]; 1789 + } pseudo; 1790 + int i; 1791 + u32 *plong; 1792 + 1793 + DEBUG(1, "ft1000_hw: copy_down_pkt()\n"); 1794 + 1795 + // Check if there is room on the FIFO 1796 + if (len > ft1000_read_fifo_len(dev)) { 1797 + udelay(10); 1798 + if (len > ft1000_read_fifo_len(dev)) { 1799 + udelay(20); 1800 + } 1801 + if (len > ft1000_read_fifo_len(dev)) { 1802 + udelay(20); 1803 + } 1804 + if (len > ft1000_read_fifo_len(dev)) { 1805 + udelay(20); 1806 + } 1807 + if (len > ft1000_read_fifo_len(dev)) { 1808 + udelay(20); 1809 + } 1810 + if (len > ft1000_read_fifo_len(dev)) { 1811 + udelay(20); 1812 + } 1813 + if (len > ft1000_read_fifo_len(dev)) { 1814 + DEBUG(1, 1815 + "ft1000_hw:ft1000_copy_down_pkt:Transmit FIFO is fulli - pkt drop\n"); 1816 + info->stats.tx_errors++; 1817 + return SUCCESS; 1818 + } 1819 + } 1820 + // Create pseudo header and send pseudo/ip to hardware 1821 + if (info->AsicID == ELECTRABUZZ_ID) { 1822 + pseudo.blk.length = len; 1823 + } else { 1824 + pseudo.blk.length = ntohs(len); 1825 + } 1826 + pseudo.blk.source = DSPID; // Need to swap to get in correct order 1827 + pseudo.blk.destination = HOSTID; 1828 + pseudo.blk.portdest = NETWORKID; // Need to swap to get in correct order 1829 + pseudo.blk.portsrc = DSPAIRID; 1830 + pseudo.blk.sh_str_id = 0; 1831 + pseudo.blk.control = 0; 1832 + pseudo.blk.rsvd1 = 0; 1833 + pseudo.blk.seq_num = 0; 1834 + pseudo.blk.rsvd2 = info->packetseqnum++; 1835 + pseudo.blk.qos_class = 0; 1836 + /* Calculate pseudo header checksum */ 1837 + pseudo.blk.checksum = pseudo.buff[0]; 1838 + for (i = 1; i < 7; i++) { 1839 + pseudo.blk.checksum ^= pseudo.buff[i]; 1840 + } 1841 + 1842 + // Production Mode 1843 + if (info->AsicID == ELECTRABUZZ_ID) { 1844 + // copy first word to UFIFO_BEG reg 1845 + ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]); 1846 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 0 BEG = 0x%04x\n", 1847 + pseudo.buff[0]); 1848 + 1849 + // copy subsequent words to UFIFO_MID reg 1850 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]); 1851 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 1 MID = 0x%04x\n", 1852 + pseudo.buff[1]); 1853 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]); 1854 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 2 MID = 0x%04x\n", 1855 + pseudo.buff[2]); 1856 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]); 1857 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 3 MID = 0x%04x\n", 1858 + pseudo.buff[3]); 1859 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]); 1860 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 4 MID = 0x%04x\n", 1861 + pseudo.buff[4]); 1862 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]); 1863 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 5 MID = 0x%04x\n", 1864 + pseudo.buff[5]); 1865 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]); 1866 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 6 MID = 0x%04x\n", 1867 + pseudo.buff[6]); 1868 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]); 1869 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 7 MID = 0x%04x\n", 1870 + pseudo.buff[7]); 1871 + 1872 + // Write PPP type + IP Packet into Downlink FIFO 1873 + for (i = 0; i < (len >> 1) - 1; i++) { 1874 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, 1875 + htons(*packet)); 1876 + DEBUG(1, 1877 + "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n", 1878 + i + 8, htons(*packet)); 1879 + packet++; 1880 + } 1881 + 1882 + // Check for odd byte 1883 + if (len & 0x0001) { 1884 + ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, 1885 + htons(*packet)); 1886 + DEBUG(1, 1887 + "ft1000_hw:ft1000_copy_down_pkt:data MID = 0x%04x\n", 1888 + htons(*packet)); 1889 + packet++; 1890 + ft1000_write_reg(dev, FT1000_REG_UFIFO_END, 1891 + htons(*packet)); 1892 + DEBUG(1, 1893 + "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n", 1894 + i + 8, htons(*packet)); 1895 + } else { 1896 + ft1000_write_reg(dev, FT1000_REG_UFIFO_END, 1897 + htons(*packet)); 1898 + DEBUG(1, 1899 + "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n", 1900 + i + 8, htons(*packet)); 1901 + } 1902 + } else { 1903 + outl(*(u32 *) & pseudo.buff[0], 1904 + dev->base_addr + FT1000_REG_MAG_UFDR); 1905 + DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n", 1906 + *(u32 *) & pseudo.buff[0]); 1907 + outl(*(u32 *) & pseudo.buff[2], 1908 + dev->base_addr + FT1000_REG_MAG_UFDR); 1909 + DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n", 1910 + *(u32 *) & pseudo.buff[2]); 1911 + outl(*(u32 *) & pseudo.buff[4], 1912 + dev->base_addr + FT1000_REG_MAG_UFDR); 1913 + DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n", 1914 + *(u32 *) & pseudo.buff[4]); 1915 + outl(*(u32 *) & pseudo.buff[6], 1916 + dev->base_addr + FT1000_REG_MAG_UFDR); 1917 + DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n", 1918 + *(u32 *) & pseudo.buff[6]); 1919 + 1920 + plong = (u32 *) packet; 1921 + // Write PPP type + IP Packet into Downlink FIFO 1922 + for (i = 0; i < (len >> 2); i++) { 1923 + outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); 1924 + } 1925 + 1926 + // Check for odd alignment 1927 + if (len & 0x0003) { 1928 + DEBUG(1, 1929 + "ft1000_hw:ft1000_copy_down_pkt:data = 0x%8x\n", 1930 + *plong); 1931 + outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); 1932 + } 1933 + outl(1, dev->base_addr + FT1000_REG_MAG_UFER); 1934 + } 1935 + 1936 + info->stats.tx_packets++; 1937 + // Add 14 bytes for MAC adddress plus ethernet type 1938 + info->stats.tx_bytes += (len + 14); 1939 + return SUCCESS; 1940 + } 1941 + 1942 + static struct net_device_stats *ft1000_stats(struct net_device *dev) 1943 + { 1944 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1945 + return (&info->stats); 1946 + } 1947 + 1948 + static int ft1000_open(struct net_device *dev) 1949 + { 1950 + 1951 + DEBUG(0, "ft1000_hw: ft1000_open is called\n"); 1952 + 1953 + ft1000_reset_card(dev); 1954 + DEBUG(0, "ft1000_hw: ft1000_open is ended\n"); 1955 + 1956 + /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP and ASIC */ 1957 + init_timer(&poll_timer); 1958 + poll_timer.expires = jiffies + (2 * HZ); 1959 + poll_timer.data = (u_long) dev; 1960 + add_timer(&poll_timer); 1961 + 1962 + DEBUG(0, "ft1000_hw: ft1000_open is ended2\n"); 1963 + return 0; 1964 + } 1965 + 1966 + static int ft1000_close(struct net_device *dev) 1967 + { 1968 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1969 + 1970 + DEBUG(0, "ft1000_hw: ft1000_close()\n"); 1971 + 1972 + info->CardReady = 0; 1973 + del_timer(&poll_timer); 1974 + 1975 + if (ft1000_card_present == 1) { 1976 + DEBUG(0, "Media is down\n"); 1977 + netif_stop_queue(dev); 1978 + 1979 + ft1000_disable_interrupts(dev); 1980 + ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT); 1981 + 1982 + //reset ASIC 1983 + ft1000_reset_asic(dev); 1984 + } 1985 + return 0; 1986 + } 1987 + 1988 + static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev) 1989 + { 1990 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 1991 + u8 *pdata; 1992 + 1993 + DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n"); 1994 + if (skb == NULL) { 1995 + DEBUG(1, "ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n"); 1996 + return 0; 1997 + } 1998 + 1999 + DEBUG(1, "ft1000_hw: ft1000_start_xmit:length of packet = %d\n", 2000 + skb->len); 2001 + 2002 + pdata = (u8 *) skb->data; 2003 + 2004 + if (info->mediastate == 0) { 2005 + /* Drop packet is mediastate is down */ 2006 + DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:mediastate is down\n"); 2007 + return SUCCESS; 2008 + } 2009 + 2010 + if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) { 2011 + /* Drop packet which has invalid size */ 2012 + DEBUG(1, 2013 + "ft1000_hw:ft1000_copy_down_pkt:invalid ethernet length\n"); 2014 + return SUCCESS; 2015 + } 2016 + ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2), 2017 + skb->len - ENET_HEADER_SIZE + 2); 2018 + 2019 + dev_kfree_skb(skb); 2020 + 2021 + return 0; 2022 + } 2023 + 2024 + static irqreturn_t ft1000_interrupt(int irq, void *dev_id) 2025 + { 2026 + struct net_device *dev = (struct net_device *)dev_id; 2027 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 2028 + u16 tempword; 2029 + u16 inttype; 2030 + int cnt; 2031 + 2032 + DEBUG(1, "ft1000_hw: ft1000_interrupt()\n"); 2033 + 2034 + if (info->CardReady == 0) { 2035 + ft1000_disable_interrupts(dev); 2036 + return IRQ_HANDLED; 2037 + } 2038 + 2039 + if (ft1000_chkcard(dev) == FALSE) { 2040 + ft1000_disable_interrupts(dev); 2041 + return IRQ_HANDLED; 2042 + } 2043 + 2044 + ft1000_disable_interrupts(dev); 2045 + 2046 + // Read interrupt type 2047 + inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); 2048 + 2049 + // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type 2050 + while (inttype) { 2051 + if (inttype & ISR_DOORBELL_PEND) { 2052 + ft1000_parse_dpram_msg(dev); 2053 + } 2054 + 2055 + if (inttype & ISR_RCV) { 2056 + DEBUG(1, "Data in FIFO\n"); 2057 + 2058 + cnt = 0; 2059 + do { 2060 + // Check if we have packets in the Downlink FIFO 2061 + if (info->AsicID == ELECTRABUZZ_ID) { 2062 + tempword = 2063 + ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT); 2064 + } else { 2065 + tempword = 2066 + ft1000_read_reg(dev, FT1000_REG_MAG_DFSR); 2067 + } 2068 + if (tempword & 0x1f) { 2069 + ft1000_copy_up_pkt(dev); 2070 + } else { 2071 + break; 2072 + } 2073 + cnt++; 2074 + } while (cnt < MAX_RCV_LOOP); 2075 + 2076 + } 2077 + // clear interrupts 2078 + tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); 2079 + DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); 2080 + ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); 2081 + 2082 + // Read interrupt type 2083 + inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR); 2084 + DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype); 2085 + } 2086 + ft1000_enable_interrupts(dev); 2087 + return IRQ_HANDLED; 2088 + } 2089 + 2090 + void stop_ft1000_card(struct net_device *dev) 2091 + { 2092 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev); 2093 + PPROV_RECORD ptr; 2094 + // int cnt; 2095 + 2096 + DEBUG(0, "ft1000_hw: stop_ft1000_card()\n"); 2097 + 2098 + info->CardReady = 0; 2099 + ft1000_card_present = 0; 2100 + netif_stop_queue(dev); 2101 + ft1000_disable_interrupts(dev); 2102 + 2103 + // Make sure we free any memory reserve for provisioning 2104 + while (list_empty(&info->prov_list) == 0) { 2105 + ptr = list_entry(info->prov_list.next, PROV_RECORD, list); 2106 + list_del(&ptr->list); 2107 + kfree(ptr->pprov_data); 2108 + kfree(ptr); 2109 + } 2110 + 2111 + if (info->registered) { 2112 + unregister_netdev(dev); 2113 + info->registered = 0; 2114 + } 2115 + 2116 + free_irq(dev->irq, dev); 2117 + release_region(dev->base_addr,256); 2118 + release_firmware(fw_entry); 2119 + flarion_ft1000_cnt--; 2120 + ft1000CleanupProc(dev); 2121 + 2122 + } 2123 + 2124 + static void ft1000_get_drvinfo(struct net_device *dev, 2125 + struct ethtool_drvinfo *info) 2126 + { 2127 + FT1000_INFO *ft_info; 2128 + ft_info = (FT1000_INFO *) netdev_priv(dev); 2129 + 2130 + snprintf(info->driver, 32, "ft1000"); 2131 + snprintf(info->bus_info, ETHTOOL_BUSINFO_LEN, "PCMCIA 0x%lx", 2132 + dev->base_addr); 2133 + snprintf(info->fw_version, 32, "%d.%d.%d.%d", ft_info->DspVer[0], 2134 + ft_info->DspVer[1], ft_info->DspVer[2], ft_info->DspVer[3]); 2135 + } 2136 + 2137 + static u32 ft1000_get_link(struct net_device *dev) 2138 + { 2139 + FT1000_INFO *info; 2140 + info = (FT1000_INFO *) netdev_priv(dev); 2141 + return info->mediastate; 2142 + } 2143 + 2144 + static const struct ethtool_ops ops = { 2145 + .get_drvinfo = ft1000_get_drvinfo, 2146 + .get_link = ft1000_get_link 2147 + }; 2148 + 2149 + struct net_device *init_ft1000_card(unsigned short irq, int port, 2150 + unsigned char *mac_addr, void *ft1000_reset, 2151 + void *link, struct device *fdev) 2152 + { 2153 + FT1000_INFO *info; 2154 + struct net_device *dev; 2155 + int i; 2156 + 2157 + static const struct net_device_ops ft1000ops = // Slavius 21.10.2009 due to kernel changes 2158 + { 2159 + .ndo_open = &ft1000_open, 2160 + .ndo_stop = &ft1000_close, 2161 + .ndo_start_xmit = &ft1000_start_xmit, 2162 + .ndo_get_stats = &ft1000_stats, 2163 + }; 2164 + 2165 + DEBUG(1, "ft1000_hw: init_ft1000_card()\n"); 2166 + DEBUG(1, "ft1000_hw: irq = %d\n", irq); 2167 + DEBUG(1, "ft1000_hw: port = 0x%04x\n", port); 2168 + 2169 + flarion_ft1000_cnt++; 2170 + 2171 + if (flarion_ft1000_cnt > 1) { 2172 + flarion_ft1000_cnt--; 2173 + 2174 + printk(KERN_INFO 2175 + "ft1000: This driver can not support more than one instance\n"); 2176 + return NULL; 2177 + } 2178 + 2179 + dev = alloc_etherdev(sizeof(FT1000_INFO)); 2180 + if (!dev) { 2181 + printk(KERN_ERR "ft1000: failed to allocate etherdev\n"); 2182 + return NULL; 2183 + } 2184 + 2185 + SET_NETDEV_DEV(dev, fdev); 2186 + info = (FT1000_INFO *) netdev_priv(dev); 2187 + 2188 + memset(info, 0, sizeof(FT1000_INFO)); 2189 + 2190 + DEBUG(1, "address of dev = 0x%8x\n", (u32) dev); 2191 + DEBUG(1, "address of dev info = 0x%8x\n", (u32) info); 2192 + DEBUG(0, "device name = %s\n", dev->name); 2193 + 2194 + memset(&info->stats, 0, sizeof(struct net_device_stats)); 2195 + 2196 + spin_lock_init(&info->dpram_lock); 2197 + info->DrvErrNum = 0; 2198 + info->ASICResetNum = 0; 2199 + info->registered = 1; 2200 + info->link = link; 2201 + info->ft1000_reset = ft1000_reset; 2202 + info->mediastate = 0; 2203 + info->fifo_cnt = 0; 2204 + info->DeviceCreated = FALSE; 2205 + info->DeviceMajor = 0; 2206 + info->CurrentInterruptEnableMask = ISR_DEFAULT_MASK; 2207 + info->InterruptsEnabled = FALSE; 2208 + info->CardReady = 0; 2209 + info->DSP_TIME[0] = 0; 2210 + info->DSP_TIME[1] = 0; 2211 + info->DSP_TIME[2] = 0; 2212 + info->DSP_TIME[3] = 0; 2213 + flarion_ft1000_cnt = 0; 2214 + 2215 + INIT_LIST_HEAD(&info->prov_list); 2216 + 2217 + info->squeseqnum = 0; 2218 + 2219 + // dev->hard_start_xmit = &ft1000_start_xmit; 2220 + // dev->get_stats = &ft1000_stats; 2221 + // dev->open = &ft1000_open; 2222 + // dev->stop = &ft1000_close; 2223 + 2224 + dev->netdev_ops = &ft1000ops; // Slavius 21.10.2009 due to kernel changes 2225 + 2226 + DEBUG(0, "device name = %s\n", dev->name); 2227 + 2228 + for (i = 0; i < 6; i++) { 2229 + dev->dev_addr[i] = mac_addr[i]; 2230 + DEBUG(1, "ft1000_hw: mac_addr %d = 0x%02x\n", i, mac_addr[i]); 2231 + } 2232 + 2233 + netif_stop_queue(dev); 2234 + dev->irq = irq; 2235 + dev->base_addr = port; 2236 + 2237 + if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) { 2238 + printk(KERN_ERR "ft1000: Could not request_irq\n"); 2239 + kfree(dev); 2240 + return (NULL); 2241 + } 2242 + 2243 + request_region(dev->base_addr, 256, dev->name); 2244 + 2245 + if (register_netdev(dev) != 0) { 2246 + DEBUG(0, "ft1000: Could not register netdev"); 2247 + return NULL; 2248 + } 2249 + 2250 + info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID); 2251 + if (info->AsicID == ELECTRABUZZ_ID) { 2252 + DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n"); 2253 + if (request_firmware(&fw_entry, "ft1000.img", fdev) != 0) { 2254 + printk(KERN_INFO "ft1000: Could not open ft1000.img\n"); 2255 + unregister_netdev(dev); 2256 + free_irq(dev->irq, dev); 2257 + kfree(dev); 2258 + return NULL; 2259 + } 2260 + } else { 2261 + DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n"); 2262 + if (request_firmware(&fw_entry, "ft2000.img", fdev) != 0) { 2263 + printk(KERN_INFO "ft1000: Could not open ft2000.img\n"); 2264 + unregister_netdev(dev); 2265 + free_irq(dev->irq, dev); 2266 + kfree(dev); 2267 + return NULL; 2268 + } 2269 + } 2270 + 2271 + ft1000_enable_interrupts(dev); 2272 + 2273 + ft1000InitProc(dev); 2274 + ft1000_card_present = 1; 2275 + SET_ETHTOOL_OPS(dev, &ops); 2276 + printk(KERN_INFO 2277 + "ft1000: %s: addr 0x%04lx irq %d, MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", 2278 + dev->name, dev->base_addr, dev->irq, dev->dev_addr[0], 2279 + dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], 2280 + dev->dev_addr[4], dev->dev_addr[5]); 2281 + return dev; 2282 + } 2283 + 2284 + EXPORT_SYMBOL(init_ft1000_card); 2285 + EXPORT_SYMBOL(stop_ft1000_card); 2286 + EXPORT_SYMBOL(flarion_ft1000_cnt);
+219
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
··· 1 + /*--------------------------------------------------------------------------- 2 + FT1000 driver for Flarion Flash OFDM NIC Device 3 + 4 + Copyright (C) 2006 Patrik Ostrihon, All rights reserved. 5 + Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved. 6 + 7 + This program is free software; you can redistribute it and/or modify it 8 + under the terms of the GNU General Public License as published by the Free 9 + Software Foundation; either version 2 of the License, or (at your option) any 10 + later version. This program is distributed in the hope that it will be useful, 11 + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + more details. You should have received a copy of the GNU General Public 14 + License along with this program; if not, write to the 15 + Free Software Foundation, Inc., 59 Temple Place - 16 + Suite 330, Boston, MA 02111-1307, USA. 17 + -----------------------------------------------------------------------------*/ 18 + 19 + #include <linux/module.h> 20 + #include <linux/kernel.h> 21 + #include <linux/proc_fs.h> 22 + #include <linux/string.h> 23 + #include <linux/vmalloc.h> 24 + #include <linux/netdevice.h> 25 + #include <asm/uaccess.h> 26 + #include "ft1000.h" 27 + 28 + #define FT1000_PROC "ft1000" 29 + #define MAX_FILE_LEN 255 30 + 31 + #define PUTM_TO_PAGE(len,page,args...) \ 32 + len += snprintf(page+len, PAGE_SIZE - len, args) 33 + 34 + #define PUTX_TO_PAGE(len,page,message,size,var) \ 35 + len += snprintf(page+len, PAGE_SIZE - len, message); \ 36 + for(i = 0; i < (size - 1); i++) \ 37 + { \ 38 + len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \ 39 + } \ 40 + len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i]) 41 + 42 + #define PUTD_TO_PAGE(len,page,message,size,var) \ 43 + len += snprintf(page+len, PAGE_SIZE - len, message); \ 44 + for(i = 0; i < (size - 1); i++) \ 45 + { \ 46 + len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \ 47 + } \ 48 + len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i]) 49 + 50 + int ft1000ReadProc(char *page, char **start, off_t off, 51 + int count, int *eof, void *data) 52 + { 53 + struct net_device *dev; 54 + int len; 55 + int i; 56 + FT1000_INFO *info; 57 + char *status[] = 58 + { "Idle (Disconnect)", "Searching", "Active (Connected)", 59 + "Waiting for L2", "Sleep", "No Coverage", "", "" 60 + }; 61 + char *signal[] = { "", "*", "**", "***", "****" }; 62 + int strength; 63 + int quality; 64 + struct timeval tv; 65 + time_t delta; 66 + 67 + dev = (struct net_device *)data; 68 + info = (FT1000_INFO *) netdev_priv(dev); 69 + 70 + if (off > 0) { 71 + *eof = 1; 72 + return 0; 73 + } 74 + 75 + /* Wrap-around */ 76 + 77 + if (info->AsicID == ELECTRABUZZ_ID) { 78 + if (info->DspHibernateFlag == 0) { 79 + if (info->ProgConStat != 0xFF) { 80 + info->LedStat = 81 + ft1000_read_dpram(dev, FT1000_DSP_LED); 82 + info->ConStat = 83 + ft1000_read_dpram(dev, 84 + FT1000_DSP_CON_STATE); 85 + } else { 86 + info->ConStat = 0xf; 87 + } 88 + } 89 + } else { 90 + if (info->ProgConStat != 0xFF) { 91 + info->LedStat = 92 + ntohs(ft1000_read_dpram_mag_16 93 + (dev, FT1000_MAG_DSP_LED, 94 + FT1000_MAG_DSP_LED_INDX)); 95 + info->ConStat = 96 + ntohs(ft1000_read_dpram_mag_16 97 + (dev, FT1000_MAG_DSP_CON_STATE, 98 + FT1000_MAG_DSP_CON_STATE_INDX)); 99 + } else { 100 + info->ConStat = 0xf; 101 + } 102 + } 103 + 104 + i = (info->LedStat) & 0xf; 105 + switch (i) { 106 + case 0x1: 107 + strength = 1; 108 + break; 109 + case 0x3: 110 + strength = 2; 111 + break; 112 + case 0x7: 113 + strength = 3; 114 + break; 115 + case 0xf: 116 + strength = 4; 117 + break; 118 + default: 119 + strength = 0; 120 + } 121 + 122 + i = (info->LedStat >> 8) & 0xf; 123 + switch (i) { 124 + case 0x1: 125 + quality = 1; 126 + break; 127 + case 0x3: 128 + quality = 2; 129 + break; 130 + case 0x7: 131 + quality = 3; 132 + break; 133 + case 0xf: 134 + quality = 4; 135 + break; 136 + default: 137 + quality = 0; 138 + } 139 + 140 + do_gettimeofday(&tv); 141 + delta = (tv.tv_sec - info->ConTm); 142 + len = 0; 143 + PUTM_TO_PAGE(len, page, "Connection Time: %02ld:%02ld:%02ld\n", 144 + ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60)); 145 + PUTM_TO_PAGE(len, page, "Connection Time[s]: %ld\n", delta); 146 + PUTM_TO_PAGE(len, page, "Asic ID: %s\n", 147 + (info->AsicID) == 148 + ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC"); 149 + PUTX_TO_PAGE(len, page, "SKU: ", SKUSZ, info->Sku); 150 + PUTX_TO_PAGE(len, page, "EUI64: ", EUISZ, info->eui64); 151 + PUTD_TO_PAGE(len, page, "DSP version number: ", DSPVERSZ, info->DspVer); 152 + PUTX_TO_PAGE(len, page, "Hardware Serial Number: ", HWSERNUMSZ, 153 + info->HwSerNum); 154 + PUTX_TO_PAGE(len, page, "Caliberation Version: ", CALVERSZ, 155 + info->RfCalVer); 156 + PUTD_TO_PAGE(len, page, "Caliberation Date: ", CALDATESZ, 157 + info->RfCalDate); 158 + PUTM_TO_PAGE(len, page, "Media State: %s\n", 159 + (info->mediastate) ? "link" : "no link"); 160 + PUTM_TO_PAGE(len, page, "Connection Status: %s\n", 161 + status[((info->ConStat) & 0x7)]); 162 + PUTM_TO_PAGE(len, page, "RX packets: %ld\n", info->stats.rx_packets); 163 + PUTM_TO_PAGE(len, page, "TX packets: %ld\n", info->stats.tx_packets); 164 + PUTM_TO_PAGE(len, page, "RX bytes: %ld\n", info->stats.rx_bytes); 165 + PUTM_TO_PAGE(len, page, "TX bytes: %ld\n", info->stats.tx_bytes); 166 + PUTM_TO_PAGE(len, page, "Signal Strength: %s\n", signal[strength]); 167 + PUTM_TO_PAGE(len, page, "Signal Quality: %s\n", signal[quality]); 168 + return len; 169 + } 170 + 171 + static int ft1000NotifyProc(struct notifier_block *this, unsigned long event, 172 + void *ptr) 173 + { 174 + struct net_device *dev = ptr; 175 + FT1000_INFO *info; 176 + 177 + info = (FT1000_INFO *) netdev_priv(dev); 178 + 179 + switch (event) { 180 + case NETDEV_CHANGENAME: 181 + remove_proc_entry(info->netdevname, info->proc_ft1000); 182 + create_proc_read_entry(dev->name, 0644, info->proc_ft1000, 183 + ft1000ReadProc, dev); 184 + snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name); 185 + break; 186 + } 187 + return NOTIFY_DONE; 188 + } 189 + 190 + static struct notifier_block ft1000_netdev_notifier = { 191 + .notifier_call = ft1000NotifyProc 192 + }; 193 + 194 + void ft1000InitProc(struct net_device *dev) 195 + { 196 + FT1000_INFO *info; 197 + 198 + info = (FT1000_INFO *) netdev_priv(dev); 199 + 200 + info->proc_ft1000 = proc_mkdir(FT1000_PROC, init_net.proc_net); 201 + create_proc_read_entry(dev->name, 0644, info->proc_ft1000, 202 + ft1000ReadProc, dev); 203 + snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name); 204 + register_netdevice_notifier(&ft1000_netdev_notifier); 205 + } 206 + 207 + void ft1000CleanupProc(struct net_device *dev) 208 + { 209 + FT1000_INFO *info; 210 + 211 + info = (FT1000_INFO *) netdev_priv(dev); 212 + 213 + remove_proc_entry(dev->name, info->proc_ft1000); 214 + remove_proc_entry(FT1000_PROC, init_net.proc_net); 215 + unregister_netdevice_notifier(&ft1000_netdev_notifier); 216 + } 217 + 218 + EXPORT_SYMBOL(ft1000InitProc); 219 + EXPORT_SYMBOL(ft1000CleanupProc);
+3
drivers/staging/ft1000/ft1000-usb/Makefile
··· 1 + obj-$(CONFIG_FT1000_USB) += ft1000.o 2 + 3 + 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
··· 1 + //--------------------------------------------------------------------------- 2 + // FT1000 driver for Flarion Flash OFDM NIC Device 3 + // 4 + // Copyright (C) 2006 Flarion Technologies, All rights reserved. 5 + // 6 + // This program is free software; you can redistribute it and/or modify it 7 + // under the terms of the GNU General Public License as published by the Free 8 + // Software Foundation; either version 2 of the License, or (at your option) any 9 + // later version. This program is distributed in the hope that it will be useful, 10 + // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + // more details. You should have received a copy of the GNU General Public 13 + // License along with this program; if not, write to the 14 + // Free Software Foundation, Inc., 59 Temple Place - 15 + // Suite 330, Boston, MA 02111-1307, USA. 16 + //--------------------------------------------------------------------------- 17 + // 18 + // File: ft1000_chdev.c 19 + // 20 + // Description: Custom character device dispatch routines. 21 + // 22 + // History: 23 + // 8/29/02 Whc Ported to Linux. 24 + // 6/05/06 Whc Porting to Linux 2.6.9 25 + // 26 + //--------------------------------------------------------------------------- 27 + #include <linux/module.h> 28 + #include <linux/kernel.h> 29 + #include <linux/sched.h> 30 + #include <linux/signal.h> 31 + #include <linux/errno.h> 32 + #include <linux/poll.h> 33 + #include <linux/netdevice.h> 34 + #include <linux/delay.h> 35 + 36 + #include <linux/fs.h> 37 + #include <linux/kmod.h> 38 + #include <linux/ioctl.h> 39 + #include <linux/unistd.h> 40 + 41 + #include "ft1000_usb.h" 42 + //#include "ft1000_ioctl.h" 43 + 44 + void ft1000_DestroyDevice(struct net_device *dev); 45 + u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow); 46 + u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx); 47 + 48 + extern inline u16 ft1000_asic_read (struct net_device *dev, u16 offset); 49 + extern inline void ft1000_asic_write (struct net_device *dev, u16 offset, u16 value); 50 + extern void CardSendCommand(struct ft1000_device *ft1000dev, unsigned short *ptempbuffer, int size); 51 + 52 + static int ft1000_ChOpen (struct inode *Inode, struct file *File); 53 + static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait); 54 + static int ft1000_ChIoctl (struct inode *Inode, struct file *File, unsigned int Command, 55 + unsigned long Argument); 56 + static int ft1000_ChRelease (struct inode *Inode, struct file *File); 57 + 58 + static int ft1000_flarion_cnt = 0; 59 + 60 + //need to looking usage of ft1000Handle 61 + 62 + 63 + 64 + // Global pointer to device object 65 + static struct ft1000_device *pdevobj[MAX_NUM_CARDS + 2]; 66 + //static devfs_handle_t ft1000Handle[MAX_NUM_CARDS]; 67 + 68 + // List to free receive command buffer pool 69 + struct list_head freercvpool; 70 + 71 + // lock to arbitrate free buffer list for receive command data 72 + spinlock_t free_buff_lock; 73 + 74 + int numofmsgbuf = 0; 75 + 76 + // Global variable to indicate that all provisioning data is sent to DSP 77 + //BOOLEAN fProvComplete; 78 + 79 + // 80 + // Table of entry-point routines for char device 81 + // 82 + static struct file_operations ft1000fops = 83 + { 84 + ioctl: ft1000_ChIoctl, 85 + poll: ft1000_ChPoll, 86 + open: ft1000_ChOpen, 87 + release: ft1000_ChRelease 88 + }; 89 + 90 + 91 + 92 + 93 + //--------------------------------------------------------------------------- 94 + // Function: exec_mknod 95 + // 96 + // Parameters: 97 + // 98 + // Returns: 99 + // 100 + // Description: 101 + // 102 + // Notes: 103 + // 104 + //--------------------------------------------------------------------------- 105 + static int exec_mknod (void *pdata) 106 + { 107 + PFT1000_INFO info; 108 + char mjnum[4]; 109 + char minornum[4]; 110 + char temp[32]; 111 + int retcode; 112 + // int i; //aelias [-] reason : unused variable 113 + char *envp[] = { "HOME=/", "PATH=/usr/bin:/bin", NULL }; 114 + char *argv[]={"-m 666",temp,"c",mjnum,minornum,NULL}; 115 + 116 + info = pdata; 117 + DEBUG("ft1000_chdev:exec_mknod is called with major number = %d\n", info->DeviceMajor); 118 + sprintf(temp, "%s%s", "/dev/", info->DeviceName) ; 119 + sprintf(mjnum, "%d", info->DeviceMajor); 120 + sprintf(minornum, "%d", info->CardNumber); 121 + 122 + //char *argv[]={"mknod","-m 666",temp,"c",mjnum,minornum,NULL}; 123 + // char *argv[]={"-m 666",temp,"c",mjnum,minornum,NULL}; 124 + 125 + //for (i=0; i<7;i++) 126 + // DEBUG("argv[%d]=%s\n", i, argv[i]); 127 + 128 + 129 + retcode = call_usermodehelper ("/bin/mknod", argv, envp, 1); 130 + if (retcode) { 131 + DEBUG("ft1000_chdev:exec_mknod failed to make the node: retcode = %d\n", retcode); 132 + } 133 + 134 + 135 + 136 + return retcode; 137 + 138 + } 139 + 140 + //--------------------------------------------------------------------------- 141 + // Function: rm_mknod 142 + // 143 + // Description: This module removes the FT1000 device file 144 + // 145 + //--------------------------------------------------------------------------- 146 + static int rm_mknod (void *pdata) 147 + { 148 + 149 + PFT1000_INFO info; 150 + //char *argv[4]={"rm", "-f", "/dev/FT1000", NULL}; 151 + int retcode; 152 + char temp[32]; 153 + char *argv[]={"rm", "-f", temp, NULL}; 154 + 155 + info = (PFT1000_INFO)pdata; 156 + DEBUG("ft1000_chdev:rm_mknod is called for device %s\n", info->DeviceName); 157 + sprintf(temp, "%s%s", "/dev/", info->DeviceName) ; 158 + 159 + // char *argv[]={"rm", "-f", temp, NULL}; 160 + 161 + retcode = call_usermodehelper ("/bin/rm", argv, NULL, 1); 162 + if (retcode) { 163 + DEBUG("ft1000_chdev:rm_mknod failed to remove the node: retcode = %d\n", retcode); 164 + } 165 + else 166 + DEBUG("ft1000_chdev:rm_mknod done!\n"); 167 + 168 + 169 + return retcode; 170 + 171 + } 172 + //--------------------------------------------------------------------------- 173 + // Function: ft1000_get_buffer 174 + // 175 + // Parameters: 176 + // 177 + // Returns: 178 + // 179 + // Description: 180 + // 181 + // Notes: 182 + // 183 + //--------------------------------------------------------------------------- 184 + PDPRAM_BLK ft1000_get_buffer (struct list_head *bufflist) 185 + { 186 + unsigned long flags; 187 + PDPRAM_BLK ptr; 188 + 189 + spin_lock_irqsave(&free_buff_lock, flags); 190 + // Check if buffer is available 191 + if ( list_empty(bufflist) ) { 192 + DEBUG("ft1000_get_buffer: No more buffer - %d\n", numofmsgbuf); 193 + ptr = NULL; 194 + } 195 + else { 196 + numofmsgbuf--; 197 + ptr = list_entry(bufflist->next, DPRAM_BLK, list); 198 + list_del(&ptr->list); 199 + //DEBUG("ft1000_get_buffer: number of free msg buffers = %d\n", numofmsgbuf); 200 + } 201 + spin_unlock_irqrestore(&free_buff_lock, flags); 202 + 203 + return ptr; 204 + } 205 + 206 + 207 + 208 + 209 + //--------------------------------------------------------------------------- 210 + // Function: ft1000_free_buffer 211 + // 212 + // Parameters: 213 + // 214 + // Returns: 215 + // 216 + // Description: 217 + // 218 + // Notes: 219 + // 220 + //--------------------------------------------------------------------------- 221 + void ft1000_free_buffer (PDPRAM_BLK pdpram_blk, struct list_head *plist) 222 + { 223 + unsigned long flags; 224 + 225 + spin_lock_irqsave(&free_buff_lock, flags); 226 + // Put memory back to list 227 + list_add_tail(&pdpram_blk->list, plist); 228 + numofmsgbuf++; 229 + //DEBUG("ft1000_free_buffer: number of free msg buffers = %d\n", numofmsgbuf); 230 + spin_unlock_irqrestore(&free_buff_lock, flags); 231 + } 232 + 233 + //--------------------------------------------------------------------------- 234 + // Function: ft1000_CreateDevice 235 + // 236 + // Parameters: dev - pointer to adapter object 237 + // 238 + // Returns: 0 if successful 239 + // 240 + // Description: Creates a private char device. 241 + // 242 + // Notes: Only called by init_module(). 243 + // 244 + //--------------------------------------------------------------------------- 245 + int ft1000_CreateDevice(struct ft1000_device *dev) 246 + { 247 + PFT1000_INFO info = netdev_priv(dev->net); 248 + int result; 249 + int i; 250 + pid_t pid; 251 + 252 + // make a new device name 253 + sprintf(info->DeviceName, "%s%d", "FT100", info->CardNumber); 254 + 255 + // Delete any existing FT1000 node 256 + pid = kernel_thread (rm_mknod,(void *)info, 0); 257 + msleep(1000); 258 + 259 + DEBUG("ft1000_CreateDevice: number of instance = %d\n", ft1000_flarion_cnt); 260 + DEBUG("DeviceCreated = %x\n", info->DeviceCreated); 261 + 262 + //save the device info to global array 263 + pdevobj[info->CardNumber] = dev; 264 + 265 + DEBUG("ft1000_CreateDevice: ******SAVED pdevobj[%d]=%x\n", info->CardNumber, (unsigned int)pdevobj[info->CardNumber]); //aelias [+] reason:up 266 + 267 + if (info->DeviceCreated) 268 + { 269 + DEBUG("ft1000_CreateDevice: \"%s\" already registered\n", info->DeviceName); 270 + return -EIO; 271 + } 272 + 273 + 274 + // register the device 275 + DEBUG("ft1000_CreateDevice: \"%s\" device registration\n", info->DeviceName); 276 + info->DeviceMajor = 0; 277 + 278 + result = register_chrdev(info->DeviceMajor, info->DeviceName, &ft1000fops); 279 + if (result < 0) 280 + { 281 + DEBUG("ft1000_CreateDevice: unable to get major %d\n", info->DeviceMajor); 282 + return result; 283 + } 284 + 285 + DEBUG("ft1000_CreateDevice: registered char device \"%s\"\n", info->DeviceName); 286 + 287 + // save a dynamic device major number 288 + if (info->DeviceMajor == 0) 289 + { 290 + info->DeviceMajor = result; 291 + DEBUG("ft1000_PcdCreateDevice: device major = %d\n", info->DeviceMajor); 292 + } 293 + 294 + // Create a thread to call user mode app to mknod 295 + pid = kernel_thread (exec_mknod, (void *)info, 0); 296 + 297 + // initialize application information 298 + info->appcnt = 0; 299 + 300 + // if (ft1000_flarion_cnt == 0) { 301 + // 302 + // DEBUG("Initialize free_buff_lock and freercvpool\n"); 303 + // spin_lock_init(&free_buff_lock); 304 + // 305 + // // initialize a list of buffers to be use for queuing up receive command data 306 + // INIT_LIST_HEAD (&freercvpool); 307 + // 308 + // // create list of free buffers 309 + // for (i=0; i<NUM_OF_FREE_BUFFERS; i++) { 310 + // // Get memory for DPRAM_DATA link list 311 + // pdpram_blk = kmalloc ( sizeof(DPRAM_BLK), GFP_KERNEL ); 312 + // // Get a block of memory to store command data 313 + // pdpram_blk->pbuffer = kmalloc ( MAX_CMD_SQSIZE, GFP_KERNEL ); 314 + // // link provisioning data 315 + // list_add_tail (&pdpram_blk->list, &freercvpool); 316 + // } 317 + // numofmsgbuf = NUM_OF_FREE_BUFFERS; 318 + // } 319 + 320 + 321 + // initialize application information 322 + info->appcnt = 0; 323 + for (i=0; i<MAX_NUM_APP; i++) { 324 + info->app_info[i].nTxMsg = 0; 325 + info->app_info[i].nRxMsg = 0; 326 + info->app_info[i].nTxMsgReject = 0; 327 + info->app_info[i].nRxMsgMiss = 0; 328 + info->app_info[i].fileobject = 0; 329 + info->app_info[i].app_id = i+1; 330 + info->app_info[i].DspBCMsgFlag = 0; 331 + info->app_info[i].NumOfMsg = 0; 332 + init_waitqueue_head(&info->app_info[i].wait_dpram_msg); 333 + INIT_LIST_HEAD (&info->app_info[i].app_sqlist); 334 + } 335 + 336 + 337 + 338 + 339 + // ft1000Handle[info->CardNumber] = devfs_register(NULL, info->DeviceName, DEVFS_FL_AUTO_DEVNUM, 0, 0, 340 + // S_IFCHR | S_IRUGO | S_IWUGO, &ft1000fops, NULL); 341 + 342 + 343 + info->DeviceCreated = TRUE; 344 + ft1000_flarion_cnt++; 345 + 346 + return result; 347 + } 348 + 349 + //--------------------------------------------------------------------------- 350 + // Function: ft1000_DestroyDeviceDEBUG 351 + // 352 + // Parameters: dev - pointer to adapter object 353 + // 354 + // Description: Destroys a private char device. 355 + // 356 + // Notes: Only called by cleanup_module(). 357 + // 358 + //--------------------------------------------------------------------------- 359 + void ft1000_DestroyDevice(struct net_device *dev) 360 + { 361 + PFT1000_INFO info = netdev_priv(dev); 362 + int result = 0; 363 + pid_t pid; 364 + int i; 365 + PDPRAM_BLK pdpram_blk; 366 + DPRAM_BLK *ptr; 367 + 368 + DEBUG("ft1000_chdev:ft1000_DestroyDevice called\n"); 369 + 370 + 371 + 372 + if (info->DeviceCreated) 373 + { 374 + ft1000_flarion_cnt--; 375 + unregister_chrdev(info->DeviceMajor, info->DeviceName); 376 + DEBUG("ft1000_DestroyDevice: unregistered device \"%s\", result = %d\n", 377 + info->DeviceName, result); 378 + 379 + pid = kernel_thread (rm_mknod, (void *)info, 0); 380 + 381 + // Make sure we free any memory reserve for slow Queue 382 + for (i=0; i<MAX_NUM_APP; i++) { 383 + while (list_empty(&info->app_info[i].app_sqlist) == 0) { 384 + pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list); 385 + list_del(&pdpram_blk->list); 386 + ft1000_free_buffer(pdpram_blk, &freercvpool); 387 + 388 + } 389 + wake_up_interruptible(&info->app_info[i].wait_dpram_msg); 390 + } 391 + 392 + // Remove buffer allocated for receive command data 393 + if (ft1000_flarion_cnt == 0) { 394 + while (list_empty(&freercvpool) == 0) { 395 + ptr = list_entry(freercvpool.next, DPRAM_BLK, list); 396 + list_del(&ptr->list); 397 + kfree(ptr->pbuffer); 398 + kfree(ptr); 399 + } 400 + } 401 + 402 + // devfs_unregister(ft1000Handle[info->CardNumber]); 403 + 404 + info->DeviceCreated = FALSE; 405 + 406 + pdevobj[info->CardNumber] = NULL; 407 + } 408 + 409 + 410 + } 411 + 412 + //--------------------------------------------------------------------------- 413 + // Function: ft1000_ChOpen 414 + // 415 + // Parameters: 416 + // 417 + // Description: 418 + // 419 + // Notes: 420 + // 421 + //--------------------------------------------------------------------------- 422 + static int ft1000_ChOpen (struct inode *Inode, struct file *File) 423 + { 424 + PFT1000_INFO info; 425 + int i,num; 426 + 427 + DEBUG("ft1000_ChOpen called\n"); 428 + num = (MINOR(Inode->i_rdev) & 0xf); 429 + DEBUG("ft1000_ChOpen: minor number=%d\n", num); 430 + 431 + for (i=0; i<5; i++) 432 + DEBUG("pdevobj[%d]=%x\n", i, (unsigned int)pdevobj[i]); //aelias [+] reason: down 433 + 434 + if ( pdevobj[num] != NULL ) 435 + //info = (PFT1000_INFO)(pdevobj[num]->net->priv); 436 + info = (FT1000_INFO *) netdev_priv (pdevobj[num]->net); 437 + else 438 + { 439 + DEBUG("ft1000_ChOpen: can not find device object %d\n", num); 440 + return -1; 441 + } 442 + 443 + DEBUG("f_owner = 0x%8x number of application = %d\n", (u32)(&File->f_owner), info->appcnt ); 444 + 445 + // Check if maximum number of application exceeded 446 + if (info->appcnt > MAX_NUM_APP) { 447 + DEBUG("Maximum number of application exceeded\n"); 448 + return -EACCES; 449 + } 450 + 451 + // Search for available application info block 452 + for (i=0; i<MAX_NUM_APP; i++) { 453 + if ( (info->app_info[i].fileobject == 0) ) { 454 + break; 455 + } 456 + } 457 + 458 + // Fail due to lack of application info block 459 + if (i == MAX_NUM_APP) { 460 + DEBUG("Could not find an application info block\n"); 461 + return -EACCES; 462 + } 463 + 464 + info->appcnt++; 465 + info->app_info[i].fileobject = (u32)(&File->f_owner); 466 + info->app_info[i].nTxMsg = 0; 467 + info->app_info[i].nRxMsg = 0; 468 + info->app_info[i].nTxMsgReject = 0; 469 + info->app_info[i].nRxMsgMiss = 0; 470 + 471 + File->private_data = pdevobj[num]->net; 472 + 473 + return 0; 474 + } 475 + 476 + 477 + //--------------------------------------------------------------------------- 478 + // Function: ft1000_ChPoll 479 + // 480 + // Parameters: 481 + // 482 + // Description: 483 + // 484 + // Notes: 485 + // 486 + //--------------------------------------------------------------------------- 487 + 488 + static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait) 489 + { 490 + struct net_device *dev = file->private_data; 491 + PFT1000_INFO info; 492 + int i; 493 + 494 + //DEBUG("ft1000_ChPoll called\n"); 495 + if (ft1000_flarion_cnt == 0) { 496 + DEBUG("FT1000:ft1000_ChPoll called when ft1000_flarion_cnt is zero\n"); 497 + return (-EBADF); 498 + } 499 + 500 + info = (FT1000_INFO *) netdev_priv (dev); 501 + 502 + // Search for matching file object 503 + for (i=0; i<MAX_NUM_APP; i++) { 504 + if ( info->app_info[i].fileobject == (u32)(&file->f_owner) ) { 505 + //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id); 506 + break; 507 + } 508 + } 509 + 510 + // Could not find application info block 511 + if (i == MAX_NUM_APP) { 512 + DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n"); 513 + return ( -EACCES ); 514 + } 515 + 516 + if (list_empty(&info->app_info[i].app_sqlist) == 0) { 517 + DEBUG("FT1000:ft1000_ChPoll:Message detected in slow queue\n"); 518 + return(POLLIN | POLLRDNORM | POLLPRI); 519 + } 520 + 521 + poll_wait (file, &info->app_info[i].wait_dpram_msg, wait); 522 + //DEBUG("FT1000:ft1000_ChPoll:Polling for data from DSP\n"); 523 + 524 + return (0); 525 + } 526 + 527 + //--------------------------------------------------------------------------- 528 + // Function: ft1000_ChIoctl 529 + // 530 + // Parameters: 531 + // 532 + // Description: 533 + // 534 + // Notes: 535 + // 536 + //--------------------------------------------------------------------------- 537 + static int ft1000_ChIoctl (struct inode *Inode, struct file *File, unsigned int Command, 538 + unsigned long Argument) 539 + { 540 + struct net_device *dev; 541 + PFT1000_INFO info; 542 + struct ft1000_device *ft1000dev; 543 + int result=0; 544 + int cmd; 545 + int i; 546 + u16 tempword; 547 + unsigned long flags; 548 + struct timeval tv; 549 + IOCTL_GET_VER get_ver_data; 550 + IOCTL_GET_DSP_STAT get_stat_data; 551 + u8 ConnectionMsg[] = {0x00,0x44,0x10,0x20,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x93,0x64, 552 + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a, 553 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 554 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 555 + 0x00,0x00,0x02,0x37,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x7f,0x00, 556 + 0x00,0x01,0x00,0x00}; 557 + 558 + unsigned short ledStat=0; 559 + unsigned short conStat=0; 560 + 561 + //DEBUG("ft1000_ChIoctl called\n"); 562 + 563 + if (ft1000_flarion_cnt == 0) { 564 + DEBUG("FT1000:ft1000_ChIoctl called when ft1000_flarion_cnt is zero\n"); 565 + return (-EBADF); 566 + } 567 + 568 + //DEBUG("FT1000:ft1000_ChIoctl:Command = 0x%x Argument = 0x%8x\n", Command, (u32)Argument); 569 + 570 + dev = File->private_data; 571 + info = (FT1000_INFO *) netdev_priv (dev); 572 + ft1000dev = info->pFt1000Dev; 573 + cmd = _IOC_NR(Command); 574 + //DEBUG("FT1000:ft1000_ChIoctl:cmd = 0x%x\n", cmd); 575 + 576 + // process the command 577 + switch (cmd) { 578 + case IOCTL_REGISTER_CMD: 579 + DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_REGISTER called\n"); 580 + result = get_user(tempword, (unsigned short *)Argument); 581 + if (result) { 582 + DEBUG("result = %d failed to get_user\n", result); 583 + break; 584 + } 585 + if (tempword == DSPBCMSGID) { 586 + // Search for matching file object 587 + for (i=0; i<MAX_NUM_APP; i++) { 588 + if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) { 589 + info->app_info[i].DspBCMsgFlag = 1; 590 + DEBUG("FT1000:ft1000_ChIoctl:Registered for broadcast messages\n"); 591 + break; 592 + } 593 + } 594 + } 595 + break; 596 + 597 + case IOCTL_GET_VER_CMD: 598 + DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_VER called\n"); 599 + 600 + get_ver_data.drv_ver = FT1000_DRV_VER; 601 + 602 + if (copy_to_user((PIOCTL_GET_VER)Argument, &get_ver_data, sizeof(get_ver_data)) ) { 603 + DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n"); 604 + result = -EFAULT; 605 + break; 606 + } 607 + 608 + DEBUG("FT1000:ft1000_ChIoctl:driver version = 0x%x\n",(unsigned int)get_ver_data.drv_ver); 609 + 610 + break; 611 + case IOCTL_CONNECT: 612 + // Connect Message 613 + DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_CONNECT\n"); 614 + ConnectionMsg[79] = 0xfc; 615 + CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c); 616 + 617 + break; 618 + case IOCTL_DISCONNECT: 619 + // Disconnect Message 620 + DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_DISCONNECT\n"); 621 + ConnectionMsg[79] = 0xfd; 622 + CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c); 623 + break; 624 + case IOCTL_GET_DSP_STAT_CMD: 625 + //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DSP_STAT called\n"); 626 + 627 + memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ); 628 + memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ); 629 + memcpy(get_stat_data.Sku, info->Sku, SKUSZ); 630 + memcpy(get_stat_data.eui64, info->eui64, EUISZ); 631 + 632 + if (info->ProgConStat != 0xFF) { 633 + ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (PUCHAR)&ledStat, FT1000_MAG_DSP_LED_INDX); 634 + get_stat_data.LedStat = ntohs(ledStat); 635 + DEBUG("FT1000:ft1000_ChIoctl: LedStat = 0x%x\n", get_stat_data.LedStat); 636 + ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (PUCHAR)&conStat, FT1000_MAG_DSP_CON_STATE_INDX); 637 + get_stat_data.ConStat = ntohs(conStat); 638 + DEBUG("FT1000:ft1000_ChIoctl: ConStat = 0x%x\n", get_stat_data.ConStat); 639 + } 640 + else { 641 + get_stat_data.ConStat = 0x0f; 642 + } 643 + 644 + 645 + get_stat_data.nTxPkts = info->stats.tx_packets; 646 + get_stat_data.nRxPkts = info->stats.rx_packets; 647 + get_stat_data.nTxBytes = info->stats.tx_bytes; 648 + get_stat_data.nRxBytes = info->stats.rx_bytes; 649 + do_gettimeofday ( &tv ); 650 + get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm); 651 + DEBUG("Connection Time = %d\n", (int)get_stat_data.ConTm); 652 + if (copy_to_user((PIOCTL_GET_DSP_STAT)Argument, &get_stat_data, sizeof(get_stat_data)) ) { 653 + DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n"); 654 + result = -EFAULT; 655 + break; 656 + } 657 + DEBUG("ft1000_chioctl: GET_DSP_STAT succeed\n"); 658 + break; 659 + case IOCTL_SET_DPRAM_CMD: 660 + { 661 + IOCTL_DPRAM_BLK dpram_data; 662 + //IOCTL_DPRAM_COMMAND dpram_command; 663 + USHORT qtype; 664 + USHORT msgsz; 665 + PPSEUDO_HDR ppseudo_hdr; 666 + PUSHORT pmsg; 667 + USHORT total_len; 668 + USHORT app_index; 669 + u16 status; 670 + 671 + //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_SET_DPRAM called\n"); 672 + 673 + 674 + if (ft1000_flarion_cnt == 0) { 675 + return (-EBADF); 676 + } 677 + 678 + if (info->DrvMsgPend) { 679 + return (-ENOTTY); 680 + } 681 + 682 + if ( (info->DspAsicReset) || (info->fProvComplete == 0) ) { 683 + return (-EACCES); 684 + } 685 + 686 + info->fAppMsgPend = 1; 687 + 688 + if (info->CardReady) { 689 + 690 + //DEBUG("FT1000:ft1000_ChIoctl: try to SET_DPRAM \n"); 691 + 692 + // Get the length field to see how many bytes to copy 693 + result = get_user(msgsz, (unsigned short *)Argument); 694 + msgsz = ntohs (msgsz); 695 + //DEBUG("FT1000:ft1000_ChIoctl: length of message = %d\n", msgsz); 696 + 697 + if (msgsz > MAX_CMD_SQSIZE) { 698 + DEBUG("FT1000:ft1000_ChIoctl: bad message length = %d\n", msgsz); 699 + result = -EINVAL; 700 + break; 701 + } 702 + 703 + //if ( copy_from_user(&(dpram_command.dpram_blk), (PIOCTL_DPRAM_BLK)Argument, msgsz+2) ) { 704 + if ( copy_from_user(&dpram_data, (PIOCTL_DPRAM_BLK)Argument, msgsz+2) ) { 705 + DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n"); 706 + result = -EFAULT; 707 + } 708 + else { 709 + #if 0 710 + // whc - for debugging only 711 + ptr = (char *)&dpram_data; 712 + for (i=0; i<msgsz; i++) { 713 + DEBUG(1,"FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++); 714 + } 715 + #endif 716 + // Check if this message came from a registered application 717 + for (i=0; i<MAX_NUM_APP; i++) { 718 + if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) { 719 + break; 720 + } 721 + } 722 + if (i==MAX_NUM_APP) { 723 + DEBUG("FT1000:No matching application fileobject\n"); 724 + result = -EINVAL; 725 + break; 726 + } 727 + app_index = i; 728 + 729 + // Check message qtype type which is the lower byte within qos_class 730 + //qtype = ntohs(dpram_command.dpram_blk.pseudohdr.qos_class) & 0xff; 731 + qtype = ntohs(dpram_data.pseudohdr.qos_class) & 0xff; 732 + //DEBUG("FT1000_ft1000_ChIoctl: qtype = %d\n", qtype); 733 + if (qtype) { 734 + } 735 + else { 736 + // Put message into Slow Queue 737 + // Only put a message into the DPRAM if msg doorbell is available 738 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL); 739 + //DEBUG("FT1000_ft1000_ChIoctl: READ REGISTER tempword=%x\n", tempword); 740 + if (tempword & FT1000_DB_DPRAM_TX) { 741 + // Suspend for 2ms and try again due to DSP doorbell busy 742 + mdelay(2); 743 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL); 744 + if (tempword & FT1000_DB_DPRAM_TX) { 745 + // Suspend for 1ms and try again due to DSP doorbell busy 746 + mdelay(1); 747 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL); 748 + if (tempword & FT1000_DB_DPRAM_TX) { 749 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL); 750 + if (tempword & FT1000_DB_DPRAM_TX) { 751 + // Suspend for 3ms and try again due to DSP doorbell busy 752 + mdelay(3); 753 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL); 754 + if (tempword & FT1000_DB_DPRAM_TX) { 755 + DEBUG("FT1000:ft1000_ChIoctl:Doorbell not available\n"); 756 + result = -ENOTTY; 757 + break; 758 + } 759 + } 760 + } 761 + } 762 + } 763 + 764 + //DEBUG("FT1000_ft1000_ChIoctl: finished reading register\n"); 765 + 766 + // Make sure we are within the limits of the slow queue memory limitation 767 + if ( (msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ) ) { 768 + // Need to put sequence number plus new checksum for message 769 + //pmsg = (PUSHORT)&dpram_command.dpram_blk.pseudohdr; 770 + pmsg = (PUSHORT)&dpram_data.pseudohdr; 771 + ppseudo_hdr = (PPSEUDO_HDR)pmsg; 772 + total_len = msgsz+2; 773 + if (total_len & 0x1) { 774 + total_len++; 775 + } 776 + 777 + // Insert slow queue sequence number 778 + ppseudo_hdr->seq_num = info->squeseqnum++; 779 + ppseudo_hdr->portsrc = info->app_info[app_index].app_id; 780 + // Calculate new checksum 781 + ppseudo_hdr->checksum = *pmsg++; 782 + //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum); 783 + for (i=1; i<7; i++) { 784 + ppseudo_hdr->checksum ^= *pmsg++; 785 + //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum); 786 + } 787 + pmsg++; 788 + ppseudo_hdr = (PPSEUDO_HDR)pmsg; 789 + #if 0 790 + ptr = (char *)&dpram_data; 791 + DEBUG("FT1000:ft1000_ChIoctl: Command Send\n"); 792 + for (i=0; i<total_len; i++) { 793 + DEBUG("FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++); 794 + } 795 + #endif 796 + //dpram_command.extra = 0; 797 + 798 + //CardSendCommand(ft1000dev,(unsigned char*)&dpram_command,total_len+2); 799 + CardSendCommand(ft1000dev,(unsigned short*)&dpram_data,total_len+2); 800 + 801 + 802 + info->app_info[app_index].nTxMsg++; 803 + break; 804 + } 805 + else { 806 + result = -EINVAL; 807 + break; 808 + } 809 + } 810 + } 811 + } 812 + else { 813 + DEBUG("FT1000:ft1000_ChIoctl: Card not ready take messages\n"); 814 + result = -EACCES; 815 + } 816 + 817 + } 818 + break; 819 + case IOCTL_GET_DPRAM_CMD: 820 + { 821 + PDPRAM_BLK pdpram_blk; 822 + PIOCTL_DPRAM_BLK pioctl_dpram; 823 + int msglen; 824 + 825 + //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM called\n"); 826 + 827 + if (ft1000_flarion_cnt == 0) { 828 + return (-EBADF); 829 + } 830 + 831 + // Search for matching file object 832 + for (i=0; i<MAX_NUM_APP; i++) { 833 + if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) { 834 + //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id); 835 + break; 836 + } 837 + } 838 + 839 + // Could not find application info block 840 + if (i == MAX_NUM_APP) { 841 + DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n"); 842 + result = -EBADF; 843 + break; 844 + } 845 + 846 + result = 0; 847 + pioctl_dpram = (PIOCTL_DPRAM_BLK)Argument; 848 + if (list_empty(&info->app_info[i].app_sqlist) == 0) { 849 + //DEBUG("FT1000:ft1000_ChIoctl:Message detected in slow queue\n"); 850 + spin_lock_irqsave(&free_buff_lock, flags); 851 + pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list); 852 + list_del(&pdpram_blk->list); 853 + info->app_info[i].NumOfMsg--; 854 + //DEBUG("FT1000:ft1000_ChIoctl:NumOfMsg for app %d = %d\n", i, info->app_info[i].NumOfMsg); 855 + spin_unlock_irqrestore(&free_buff_lock, flags); 856 + msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ; 857 + pioctl_dpram->total_len = htons(msglen); 858 + //DEBUG("FT1000:ft1000_ChIoctl:msg length = %x\n", msglen); 859 + if(copy_to_user (&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) 860 + { 861 + DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n"); 862 + result = -EFAULT; 863 + break; 864 + } 865 + 866 + ft1000_free_buffer(pdpram_blk, &freercvpool); 867 + result = msglen; 868 + } 869 + //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM no message\n"); 870 + } 871 + break; 872 + 873 + default: 874 + DEBUG("FT1000:ft1000_ChIoctl:unknown command: 0x%x\n", Command); 875 + result = -ENOTTY; 876 + break; 877 + } 878 + info->fAppMsgPend = 0; 879 + return result; 880 + } 881 + 882 + //--------------------------------------------------------------------------- 883 + // Function: ft1000_ChRelease 884 + // 885 + // Parameters: 886 + // 887 + // Description: 888 + // 889 + // Notes: 890 + // 891 + //--------------------------------------------------------------------------- 892 + static int ft1000_ChRelease (struct inode *Inode, struct file *File) 893 + { 894 + PFT1000_INFO info; 895 + struct net_device *dev; 896 + int i; 897 + PDPRAM_BLK pdpram_blk; 898 + 899 + DEBUG("ft1000_ChRelease called\n"); 900 + 901 + dev = File->private_data; 902 + info = (FT1000_INFO *) netdev_priv (dev); 903 + 904 + if (ft1000_flarion_cnt == 0) { 905 + info->appcnt--; 906 + return (-EBADF); 907 + } 908 + 909 + // Search for matching file object 910 + for (i=0; i<MAX_NUM_APP; i++) { 911 + if ( info->app_info[i].fileobject == (u32)(&File->f_owner) ) { 912 + //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id); 913 + break; 914 + } 915 + } 916 + 917 + if (i==MAX_NUM_APP) 918 + return 0; 919 + 920 + while (list_empty(&info->app_info[i].app_sqlist) == 0) { 921 + DEBUG("Remove and free memory queue up on slow queue\n"); 922 + pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, DPRAM_BLK, list); 923 + list_del(&pdpram_blk->list); 924 + ft1000_free_buffer(pdpram_blk, &freercvpool); 925 + } 926 + 927 + // initialize application information 928 + info->appcnt--; 929 + DEBUG("ft1000_chdev:%s:appcnt = %d\n", __FUNCTION__, info->appcnt); 930 + info->app_info[i].fileobject = 0; 931 + 932 + return 0; 933 + } 934 +
+1416
drivers/staging/ft1000/ft1000-usb/ft1000_download.c
··· 1 + //===================================================== 2 + // CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. 3 + // 4 + // 5 + // This file is part of Express Card USB Driver 6 + // 7 + // $Id: 8 + //==================================================== 9 + // 20090926; aelias; removed compiler warnings; ubuntu 9.04; 2.6.28-15-generic 10 + 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/netdevice.h> 15 + #include <linux/etherdevice.h> 16 + #include <linux/usb.h> 17 + #include <linux/vmalloc.h> 18 + #include "ft1000_usb.h" 19 + 20 + #define FIFO_DNLD 1 21 + 22 + #define DWNLD_HANDSHAKE_LOC 0x02 23 + #define DWNLD_TYPE_LOC 0x04 24 + #define DWNLD_SIZE_MSW_LOC 0x06 25 + #define DWNLD_SIZE_LSW_LOC 0x08 26 + #define DWNLD_PS_HDR_LOC 0x0A 27 + 28 + #define MAX_DSP_WAIT_LOOPS 40 29 + #define DSP_WAIT_SLEEP_TIME 1000 /* 1 millisecond */ 30 + #define DSP_WAIT_DISPATCH_LVL 50 /* 50 usec */ 31 + 32 + #define HANDSHAKE_TIMEOUT_VALUE 0xF1F1 33 + #define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */ 34 + #define HANDSHAKE_RESET_VALUE_USB 0xFE7E /* When DSP requests startover */ 35 + #define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */ 36 + #define HANDSHAKE_DSP_BL_READY_USB 0xFE7E /* At start DSP writes this when bootloader ready */ 37 + #define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */ 38 + #define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */ 39 + 40 + #define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */ 41 + #define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */ 42 + 43 + #define REQUEST_CODE_LENGTH 0x0000 44 + #define REQUEST_RUN_ADDRESS 0x0001 45 + #define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */ 46 + #define REQUEST_DONE_BL 0x0003 47 + #define REQUEST_DONE_CL 0x0004 48 + #define REQUEST_VERSION_INFO 0x0005 49 + #define REQUEST_CODE_BY_VERSION 0x0006 50 + #define REQUEST_MAILBOX_DATA 0x0007 51 + #define REQUEST_FILE_CHECKSUM 0x0008 52 + 53 + #define STATE_START_DWNLD 0x01 54 + #define STATE_BOOT_DWNLD 0x02 55 + #define STATE_CODE_DWNLD 0x03 56 + #define STATE_DONE_DWNLD 0x04 57 + #define STATE_SECTION_PROV 0x05 58 + #define STATE_DONE_PROV 0x06 59 + #define STATE_DONE_FILE 0x07 60 + 61 + #define MAX_LENGTH 0x7f0 62 + 63 + // Temporary download mechanism for Magnemite 64 + #define DWNLD_MAG_TYPE_LOC 0x00 65 + #define DWNLD_MAG_LEN_LOC 0x01 66 + #define DWNLD_MAG_ADDR_LOC 0x02 67 + #define DWNLD_MAG_CHKSUM_LOC 0x03 68 + #define DWNLD_MAG_VAL_LOC 0x04 69 + 70 + #define HANDSHAKE_MAG_DSP_BL_READY 0xFEFE0000 /* At start DSP writes this when bootloader ready */ 71 + #define HANDSHAKE_MAG_DSP_ENTRY 0x01000000 /* Dsp writes this to request for entry address */ 72 + #define HANDSHAKE_MAG_DSP_DATA 0x02000000 /* Dsp writes this to request for data block */ 73 + #define HANDSHAKE_MAG_DSP_DONE 0x03000000 /* Dsp writes this to indicate download done */ 74 + 75 + #define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */ 76 + #define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB /* Driver writes this to indicate data available to DSP */ 77 + #define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB /* Driver writes this to indicate entry point to DSP */ 78 + 79 + #define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1 80 + 81 + 82 + // New Magnemite downloader 83 + #define DWNLD_MAG1_HANDSHAKE_LOC 0x00 84 + #define DWNLD_MAG1_TYPE_LOC 0x01 85 + #define DWNLD_MAG1_SIZE_LOC 0x02 86 + #define DWNLD_MAG1_PS_HDR_LOC 0x03 87 + 88 + #pragma pack (push, pack_save, 1) 89 + typedef struct _DSP_FILE_HDR { 90 + long build_date; 91 + long dsp_coff_date; 92 + long loader_code_address; 93 + long loader_code_size; 94 + long loader_code_end; 95 + long dsp_code_address; 96 + long dsp_code_size; 97 + long dsp_code_end; 98 + long reserved[8]; 99 + } DSP_FILE_HDR, *PDSP_FILE_HDR; 100 + 101 + typedef struct _DSP_FILE_HDR_5 { 102 + long version_id; // Version ID of this image format. 103 + long package_id; // Package ID of code release. 104 + long build_date; // Date/time stamp when file was built. 105 + long commands_offset; // Offset to attached commands in Pseudo Hdr format. 106 + long loader_offset; // Offset to bootloader code. 107 + long loader_code_address; // Start address of bootloader. 108 + long loader_code_end; // Where bootloader code ends. 109 + long loader_code_size; 110 + long version_data_offset; // Offset were scrambled version data begins. 111 + long version_data_size; // Size, in words, of scrambled version data. 112 + long nDspImages; // Number of DSP images in file. 113 + } DSP_FILE_HDR_5, * PDSP_FILE_HDR_5; 114 + 115 + typedef struct _DSP_IMAGE_INFO { 116 + long coff_date; // Date/time when DSP Coff image was built. 117 + long begin_offset; // Offset in file where image begins. 118 + long end_offset; // Offset in file where image begins. 119 + long run_address; // On chip Start address of DSP code. 120 + long image_size; // Size of image. 121 + long version; // Embedded version # of DSP code. 122 + } DSP_IMAGE_INFO, *PDSP_IMAGE_INFO; 123 + 124 + typedef struct _DSP_IMAGE_INFO_V6 { 125 + long coff_date; // Date/time when DSP Coff image was built. 126 + long begin_offset; // Offset in file where image begins. 127 + long end_offset; // Offset in file where image begins. 128 + long run_address; // On chip Start address of DSP code. 129 + long image_size; // Size of image. 130 + long version; // Embedded version # of DSP code. 131 + unsigned short checksum; // DSP File checksum 132 + unsigned short pad1; 133 + } DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6; 134 + 135 + 136 + u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx); 137 + u16 ft1000_write_register(struct ft1000_device *ft1000dev, USHORT value, u16 nRegIndx); 138 + u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt); 139 + u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt); 140 + u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow); 141 + u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, USHORT indx, USHORT value, u8 highlow); 142 + u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer); 143 + u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer); 144 + 145 + //--------------------------------------------------------------------------- 146 + // Function: getfw 147 + // 148 + // Parameters: char *fn - input DSP image file name 149 + // int *pimgsz - output DSP image file size 150 + // Returns: DSP image buffer 151 + // 152 + // Description: Read the DSP image file into a char buffer 153 + // 154 + // Notes: 155 + // 156 + //--------------------------------------------------------------------------- 157 + char *getfw (char *fn, int *pimgsz) 158 + { 159 + struct file *fd; 160 + mm_segment_t fs = get_fs(); 161 + loff_t pos; 162 + char *pfwimg; 163 + int fwimgsz; 164 + 165 + set_fs(get_ds()); 166 + 167 + fd = filp_open(fn, 0, 0); 168 + if ( IS_ERR(fd) ) 169 + { 170 + DEBUG("FT1000:%s:can not open dsp image\n", __FUNCTION__); 171 + set_fs(fs); 172 + return NULL; 173 + } 174 + 175 + fwimgsz = i_size_read(fd->f_dentry->d_inode); 176 + *pimgsz = fwimgsz; 177 + 178 + if (fwimgsz <= 0) 179 + { 180 + DEBUG("FT1000:%s:invalid file size\n", __FUNCTION__); 181 + filp_close(fd, current->files); 182 + set_fs(fs); 183 + return NULL; 184 + } 185 + pfwimg = (char*)vmalloc ( fwimgsz ); 186 + if (pfwimg == NULL) { 187 + DEBUG("FT1000:%s:can not allocate memory for dsp image\n", __FUNCTION__); 188 + filp_close(fd, current->files); 189 + set_fs(fs); 190 + return NULL; 191 + } 192 + pos = 0; 193 + if (vfs_read(fd, pfwimg, fwimgsz, &pos) != fwimgsz) { 194 + vfree(pfwimg); 195 + DEBUG("FT1000:%s:failed to read firmware image\n",__FUNCTION__); 196 + filp_close(fd, current->files); 197 + set_fs(fs); 198 + return NULL; 199 + } 200 + 201 + filp_close(fd, current->files); 202 + set_fs(fs); 203 + 204 + return pfwimg; 205 + } 206 + 207 + //--------------------------------------------------------------------------- 208 + // Function: check_usb_db 209 + // 210 + // Parameters: struct ft1000_device - device structure 211 + // 212 + // Returns: 0 - success 213 + // 214 + // Description: This function checks if the doorbell register is cleared 215 + // 216 + // Notes: 217 + // 218 + //--------------------------------------------------------------------------- 219 + ULONG check_usb_db (struct ft1000_device *ft1000dev) 220 + { 221 + int loopcnt; 222 + USHORT temp; 223 + ULONG status; 224 + 225 + loopcnt = 0; 226 + while (loopcnt < 10) 227 + { 228 + 229 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL); 230 + DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n", temp); 231 + if (temp & 0x0080) 232 + { 233 + DEBUG("FT1000:Got checkusb doorbell\n"); 234 + status = ft1000_write_register (ft1000dev, 0x0080, FT1000_REG_DOORBELL); 235 + #if FIFO_DNLD 236 + status = ft1000_write_register (ft1000dev, 0x0100, FT1000_REG_DOORBELL); 237 + #endif 238 + status = ft1000_write_register (ft1000dev, 0x8000, FT1000_REG_DOORBELL); 239 + break; 240 + } 241 + else 242 + { 243 + loopcnt++; 244 + msleep (10); 245 + } 246 + 247 + } //end of while 248 + 249 + 250 + loopcnt = 0; 251 + while (loopcnt < 20) 252 + { 253 + 254 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL); 255 + DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp); 256 + if (temp & 0x8000) 257 + { 258 + loopcnt++; 259 + msleep (10); 260 + } 261 + else 262 + { 263 + DEBUG("check_usb_db: door bell is cleared, return 0\n"); 264 + return 0; 265 + } 266 + #if 0 267 + // Check if Card is present 268 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_SUP_IMASK); 269 + if (temp == 0x0000) { 270 + break; 271 + } 272 + 273 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_ASIC_ID); 274 + if (temp == 0xffff) { 275 + break; 276 + } 277 + #endif 278 + } 279 + 280 + return HANDSHAKE_MAG_TIMEOUT_VALUE; 281 + 282 + } 283 + 284 + //--------------------------------------------------------------------------- 285 + // Function: get_handshake 286 + // 287 + // Parameters: struct ft1000_device - device structure 288 + // USHORT expected_value - the handshake value expected 289 + // 290 + // Returns: handshakevalue - success 291 + // HANDSHAKE_TIMEOUT_VALUE - failure 292 + // 293 + // Description: This function gets the handshake and compare with the expected value 294 + // 295 + // Notes: 296 + // 297 + //--------------------------------------------------------------------------- 298 + USHORT get_handshake(struct ft1000_device *ft1000dev, USHORT expected_value) 299 + { 300 + USHORT handshake; 301 + int loopcnt; 302 + ULONG status=0; 303 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 304 + 305 + loopcnt = 0; 306 + while (loopcnt < 100) 307 + { 308 + 309 + #if FIFO_DNLD 310 + // Need to clear downloader doorbell if Hartley ASIC 311 + status = ft1000_write_register (ft1000dev, FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL); 312 + //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp); 313 + if (pft1000info->fcodeldr) 314 + { 315 + DEBUG(" get_handshake: fcodeldr is %d\n", pft1000info->fcodeldr); 316 + pft1000info->fcodeldr = 0; 317 + status = check_usb_db(ft1000dev); 318 + if (status != STATUS_SUCCESS) 319 + { 320 + DEBUG("get_handshake: check_usb_db failed\n"); 321 + status = STATUS_FAILURE; 322 + break; 323 + } 324 + status = ft1000_write_register (ft1000dev, FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL); 325 + } 326 + 327 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); 328 + //DEBUG("get_handshake: handshake is %x\n", tempx); 329 + handshake = ntohs(handshake); 330 + //DEBUG("get_handshake: after swap, handshake is %x\n", handshake); 331 + #else 332 + // Need to clear downloader doorbell if Hartley ASIC 333 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL); 334 + //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp); 335 + if (temp) 336 + { 337 + if (temp & FT1000_DB_DNLD_RX) 338 + { 339 + //DEBUG("get_handshake: write FT1000_DB_DNLD_RX to doorbell register\n"); 340 + status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL); 341 + } 342 + 343 + if (pft1000info->fcodeldr) 344 + { 345 + DEBUG(" get_handshake: fcodeldr is %d\n", pft1000info->fcodeldr); 346 + pft1000info->fcodeldr = 0; 347 + status = check_usb_db(ft1000dev); 348 + if (status != STATUS_SUCCESS) 349 + { 350 + DEBUG("get_handshake: check_usb_db failed\n"); 351 + status = STATUS_FAILURE; 352 + break; 353 + } 354 + 355 + status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL); 356 + //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp); 357 + if (temp) 358 + { 359 + if (temp & FT1000_DB_DNLD_RX) 360 + status = ft1000_write_register(ft1000dev,FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL); 361 + } 362 + } 363 + 364 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); 365 + //DEBUG("get_handshake: handshake is %x\n", tempx); 366 + handshake = ntohs(handshake); 367 + //DEBUG("get_handshake: after swap, handshake is %x\n", handshake); 368 + 369 + } //end of if temp 370 + #endif 371 + 372 + 373 + if (status) 374 + return HANDSHAKE_TIMEOUT_VALUE; 375 + 376 + //DEBUG("get_handshake: handshake= %x\n", handshake); 377 + if ((handshake == expected_value) || (handshake == HANDSHAKE_RESET_VALUE_USB)) 378 + { 379 + //DEBUG("get_handshake: return handshake %x\n", handshake); 380 + return handshake; 381 + } 382 + else 383 + { 384 + loopcnt++; 385 + msleep (10); 386 + } 387 + //DEBUG("HANDSHKE LOOP: %d\n", loopcnt); 388 + 389 + } 390 + 391 + //DEBUG("get_handshake: return handshake time out\n"); 392 + return HANDSHAKE_TIMEOUT_VALUE; 393 + } 394 + 395 + //--------------------------------------------------------------------------- 396 + // Function: put_handshake 397 + // 398 + // Parameters: struct ft1000_device - device structure 399 + // USHORT handshake_value - handshake to be written 400 + // 401 + // Returns: none 402 + // 403 + // Description: This function write the handshake value to the handshake location 404 + // in DPRAM 405 + // 406 + // Notes: 407 + // 408 + //--------------------------------------------------------------------------- 409 + void put_handshake(struct ft1000_device *ft1000dev,USHORT handshake_value) 410 + { 411 + ULONG tempx; 412 + USHORT tempword; 413 + int i; 414 + ULONG status; 415 + 416 + 417 + 418 + tempx = (ULONG)handshake_value; 419 + tempx = ntohl(tempx); 420 + 421 + tempword = (USHORT)(tempx & 0xffff); 422 + status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 0); 423 + tempword = (USHORT)(tempx >> 16); 424 + status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 1); 425 + status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL); 426 + #if FIFO_DNLD 427 + for (i=0; i<1000; i++); 428 + #else 429 + for (i=0; i<10; i++) 430 + { 431 + status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_DOORBELL); 432 + if ((tempword & FT1000_DB_DNLD_TX) == 0) 433 + break; 434 + } 435 + if (i==10) 436 + { 437 + DEBUG("FT1000:put_handshake could not clear Tx doorbell\n"); 438 + status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_DOORBELL); 439 + DEBUG("FT1000:put_handshake:doorbell = 0x%x\n",tempword); 440 + } 441 + #endif 442 + 443 + } 444 + 445 + USHORT get_handshake_usb(struct ft1000_device *ft1000dev, USHORT expected_value) 446 + { 447 + USHORT handshake; 448 + int loopcnt; 449 + USHORT temp; 450 + ULONG status=0; 451 + 452 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 453 + loopcnt = 0; 454 + handshake = 0; 455 + while (loopcnt < 100) 456 + { 457 + if (pft1000info->usbboot == 2) { 458 + status = ft1000_read_dpram32 (ft1000dev, 0, (PUCHAR)&(pft1000info->tempbuf[0]), 64); 459 + for (temp=0; temp<16; temp++) 460 + DEBUG("tempbuf %d = 0x%x\n", temp, pft1000info->tempbuf[temp]); 461 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); 462 + DEBUG("handshake from read_dpram16 = 0x%x\n", handshake); 463 + if (pft1000info->dspalive == pft1000info->tempbuf[6]) 464 + handshake = 0; 465 + else { 466 + handshake = pft1000info->tempbuf[1]; 467 + pft1000info->dspalive = pft1000info->tempbuf[6]; 468 + } 469 + } 470 + else { 471 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); 472 + } 473 + loopcnt++; 474 + msleep(10); 475 + handshake = ntohs(handshake); 476 + if ((handshake == expected_value) || (handshake == HANDSHAKE_RESET_VALUE_USB)) 477 + { 478 + return handshake; 479 + } 480 + } 481 + 482 + return HANDSHAKE_TIMEOUT_VALUE; 483 + } 484 + 485 + void put_handshake_usb(struct ft1000_device *ft1000dev,USHORT handshake_value) 486 + { 487 + int i; 488 + 489 + for (i=0; i<1000; i++); 490 + } 491 + 492 + //--------------------------------------------------------------------------- 493 + // Function: get_request_type 494 + // 495 + // Parameters: struct ft1000_device - device structure 496 + // 497 + // Returns: request type - success 498 + // 499 + // Description: This function returns the request type 500 + // 501 + // Notes: 502 + // 503 + //--------------------------------------------------------------------------- 504 + USHORT get_request_type(struct ft1000_device *ft1000dev) 505 + { 506 + USHORT request_type; 507 + ULONG status; 508 + USHORT tempword; 509 + ULONG tempx; 510 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 511 + 512 + if ( pft1000info->bootmode == 1) 513 + { 514 + status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempx); 515 + tempx = ntohl(tempx); 516 + } 517 + else 518 + { 519 + #if FIFO_DNLD 520 + tempx = 0; 521 + #else 522 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempword, 0); 523 + tempx = tempword; 524 + #endif 525 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempword, 1); 526 + tempx |= (tempword << 16); 527 + tempx = ntohl(tempx); 528 + } 529 + request_type = (USHORT)tempx; 530 + 531 + //DEBUG("get_request_type: request_type is %x\n", request_type); 532 + return request_type; 533 + 534 + } 535 + 536 + USHORT get_request_type_usb(struct ft1000_device *ft1000dev) 537 + { 538 + USHORT request_type; 539 + ULONG status; 540 + USHORT tempword; 541 + ULONG tempx; 542 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 543 + if ( pft1000info->bootmode == 1) 544 + { 545 + status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempx); 546 + tempx = ntohl(tempx); 547 + } 548 + else 549 + { 550 + if (pft1000info->usbboot == 2) { 551 + tempx = pft1000info->tempbuf[2]; 552 + tempword = pft1000info->tempbuf[3]; 553 + } 554 + else { 555 + tempx = 0; 556 + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempword, 1); 557 + } 558 + tempx |= (tempword << 16); 559 + tempx = ntohl(tempx); 560 + } 561 + request_type = (USHORT)tempx; 562 + 563 + //DEBUG("get_request_type: request_type is %x\n", request_type); 564 + return request_type; 565 + 566 + } 567 + 568 + //--------------------------------------------------------------------------- 569 + // Function: get_request_value 570 + // 571 + // Parameters: struct ft1000_device - device structure 572 + // 573 + // Returns: request value - success 574 + // 575 + // Description: This function returns the request value 576 + // 577 + // Notes: 578 + // 579 + //--------------------------------------------------------------------------- 580 + long get_request_value(struct ft1000_device *ft1000dev) 581 + { 582 + ULONG value; 583 + USHORT tempword; 584 + ULONG status; 585 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 586 + 587 + 588 + if ( pft1000info->bootmode == 1) 589 + { 590 + status = fix_ft1000_read_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&value); 591 + value = ntohl(value); 592 + } 593 + else 594 + { 595 + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 0); 596 + value = tempword; 597 + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 1); 598 + value |= (tempword << 16); 599 + value = ntohl(value); 600 + } 601 + 602 + 603 + //DEBUG("get_request_value: value is %x\n", value); 604 + return value; 605 + 606 + } 607 + 608 + long get_request_value_usb(struct ft1000_device *ft1000dev) 609 + { 610 + ULONG value; 611 + USHORT tempword; 612 + ULONG status; 613 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 614 + 615 + if (pft1000info->usbboot == 2) { 616 + value = pft1000info->tempbuf[4]; 617 + tempword = pft1000info->tempbuf[5]; 618 + } 619 + else { 620 + value = 0; 621 + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 1); 622 + } 623 + 624 + value |= (tempword << 16); 625 + value = ntohl(value); 626 + 627 + #if FIFO_DNLD 628 + if (pft1000info->usbboot == 1) 629 + pft1000info->usbboot = 2; 630 + #endif 631 + 632 + //DEBUG("get_request_value_usb: value is %x\n", value); 633 + return value; 634 + 635 + } 636 + 637 + //--------------------------------------------------------------------------- 638 + // Function: put_request_value 639 + // 640 + // Parameters: struct ft1000_device - device structure 641 + // long lvalue - value to be put into DPRAM location DWNLD_MAG1_SIZE_LOC 642 + // 643 + // Returns: none 644 + // 645 + // Description: This function writes a value to DWNLD_MAG1_SIZE_LOC 646 + // 647 + // Notes: 648 + // 649 + //--------------------------------------------------------------------------- 650 + void put_request_value(struct ft1000_device *ft1000dev, long lvalue) 651 + { 652 + ULONG tempx; 653 + ULONG status; 654 + 655 + tempx = ntohl(lvalue); 656 + status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempx); 657 + 658 + 659 + 660 + //DEBUG("put_request_value: value is %x\n", lvalue); 661 + 662 + } 663 + 664 + 665 + 666 + //--------------------------------------------------------------------------- 667 + // Function: hdr_checksum 668 + // 669 + // Parameters: PPSEUDO_HDR pHdr - Pseudo header pointer 670 + // 671 + // Returns: checksum - success 672 + // 673 + // Description: This function returns the checksum of the pseudo header 674 + // 675 + // Notes: 676 + // 677 + //--------------------------------------------------------------------------- 678 + USHORT hdr_checksum(PPSEUDO_HDR pHdr) 679 + { 680 + USHORT *usPtr = (USHORT *)pHdr; 681 + USHORT chksum; 682 + 683 + 684 + chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^ 685 + usPtr[4]) ^ usPtr[5]) ^ usPtr[6]); 686 + 687 + return chksum; 688 + } 689 + 690 + 691 + //--------------------------------------------------------------------------- 692 + // Function: write_blk 693 + // 694 + // Parameters: struct ft1000_device - device structure 695 + // USHORT **pUsFile - DSP image file pointer in USHORT 696 + // UCHAR **pUcFile - DSP image file pointer in UCHAR 697 + // long word_length - lenght of the buffer to be written 698 + // to DPRAM 699 + // 700 + // Returns: STATUS_SUCCESS - success 701 + // STATUS_FAILURE - failure 702 + // 703 + // Description: This function writes a block of DSP image to DPRAM 704 + // 705 + // Notes: 706 + // 707 + //--------------------------------------------------------------------------- 708 + ULONG write_blk (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR **pUcFile, long word_length) 709 + { 710 + ULONG Status = STATUS_SUCCESS; 711 + USHORT dpram; 712 + long temp_word_length; 713 + int loopcnt, i, j; 714 + USHORT *pTempFile; 715 + USHORT tempword; 716 + USHORT tempbuffer[64]; 717 + USHORT resultbuffer[64]; 718 + PFT1000_INFO pft1000info = netdev_priv(ft1000dev->net); 719 + 720 + //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length); 721 + dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; 722 + tempword = *(*pUsFile); 723 + (*pUsFile)++; 724 + Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0); 725 + tempword = *(*pUsFile); 726 + (*pUsFile)++; 727 + Status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1); 728 + 729 + *pUcFile = *pUcFile + 4; 730 + word_length--; 731 + tempword = (USHORT)word_length; 732 + word_length = (word_length / 16) + 1; 733 + pTempFile = *pUsFile; 734 + temp_word_length = word_length; 735 + for (; word_length > 0; word_length--) /* In words */ 736 + { 737 + loopcnt = 0; 738 + 739 + for (i=0; i<32; i++) 740 + { 741 + if (tempword != 0) 742 + { 743 + tempbuffer[i++] = *(*pUsFile); 744 + (*pUsFile)++; 745 + tempbuffer[i] = *(*pUsFile); 746 + (*pUsFile)++; 747 + *pUcFile = *pUcFile + 4; 748 + loopcnt++; 749 + tempword--; 750 + } 751 + else 752 + { 753 + tempbuffer[i++] = 0; 754 + tempbuffer[i] = 0; 755 + } 756 + } 757 + 758 + //DEBUG("write_blk: loopcnt is %d\n", loopcnt); 759 + //DEBUG("write_blk: bootmode = %d\n", bootmode); 760 + //DEBUG("write_blk: dpram = %x\n", dpram); 761 + if (pft1000info->bootmode == 0) 762 + { 763 + if (dpram >= 0x3F4) 764 + Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 8); 765 + else 766 + Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 64); 767 + } 768 + else 769 + { 770 + for (j=0; j<10; j++) 771 + { 772 + Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 64); 773 + if (Status == STATUS_SUCCESS) 774 + { 775 + // Work around for ASIC bit stuffing problem. 776 + if ( (tempbuffer[31] & 0xfe00) == 0xfe00) 777 + { 778 + Status = ft1000_write_dpram32(ft1000dev, dpram+12, (PUCHAR)&tempbuffer[24], 64); 779 + } 780 + // Let's check the data written 781 + Status = ft1000_read_dpram32 (ft1000dev, dpram, (PUCHAR)&resultbuffer[0], 64); 782 + if ( (tempbuffer[31] & 0xfe00) == 0xfe00) 783 + { 784 + for (i=0; i<28; i++) 785 + { 786 + if (resultbuffer[i] != tempbuffer[i]) 787 + { 788 + //NdisMSleep (100); 789 + DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n"); 790 + msleep(10); 791 + Status = STATUS_FAILURE; 792 + break; 793 + } 794 + } 795 + Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (PUCHAR)&resultbuffer[0], 64); 796 + for (i=0; i<16; i++) 797 + { 798 + if (resultbuffer[i] != tempbuffer[i+24]) 799 + { 800 + //NdisMSleep (100); 801 + DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n"); 802 + msleep(10); 803 + Status = STATUS_FAILURE; 804 + break; 805 + } 806 + } 807 + } 808 + else 809 + { 810 + for (i=0; i<32; i++) 811 + { 812 + if (resultbuffer[i] != tempbuffer[i]) 813 + { 814 + //NdisMSleep (100); 815 + DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n"); 816 + msleep(10); 817 + Status = STATUS_FAILURE; 818 + break; 819 + } 820 + } 821 + } 822 + 823 + if (Status == STATUS_SUCCESS) 824 + break; 825 + 826 + } 827 + } 828 + 829 + if (Status != STATUS_SUCCESS) 830 + { 831 + DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]); 832 + break; 833 + } 834 + 835 + } 836 + dpram = dpram + loopcnt; 837 + } 838 + 839 + return Status; 840 + } 841 + 842 + static void usb_dnld_complete (struct urb *urb) 843 + { 844 + //DEBUG("****** usb_dnld_complete\n"); 845 + } 846 + 847 + //--------------------------------------------------------------------------- 848 + // Function: write_blk_fifo 849 + // 850 + // Parameters: struct ft1000_device - device structure 851 + // USHORT **pUsFile - DSP image file pointer in USHORT 852 + // UCHAR **pUcFile - DSP image file pointer in UCHAR 853 + // long word_length - lenght of the buffer to be written 854 + // to DPRAM 855 + // 856 + // Returns: STATUS_SUCCESS - success 857 + // STATUS_FAILURE - failure 858 + // 859 + // Description: This function writes a block of DSP image to DPRAM 860 + // 861 + // Notes: 862 + // 863 + //--------------------------------------------------------------------------- 864 + ULONG write_blk_fifo (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR **pUcFile, long word_length) 865 + { 866 + ULONG Status = STATUS_SUCCESS; 867 + int byte_length; 868 + long aligncnt; 869 + 870 + byte_length = word_length * 4; 871 + 872 + if (byte_length % 4) 873 + aligncnt = 4 - (byte_length % 4); 874 + else 875 + aligncnt = 0; 876 + byte_length += aligncnt; 877 + 878 + if (byte_length && ((byte_length % 64) == 0)) { 879 + byte_length += 4; 880 + } 881 + 882 + if (byte_length < 64) 883 + byte_length = 68; 884 + 885 + #if 0 886 + pblk = kzalloc(byte_length, GFP_KERNEL); 887 + memcpy (pblk, *pUcFile, byte_length); 888 + 889 + pipe = usb_sndbulkpipe (ft1000dev->dev, ft1000dev->bulk_out_endpointAddr); 890 + 891 + Status = usb_bulk_msg (ft1000dev->dev, 892 + pipe, 893 + pblk, 894 + byte_length, 895 + &cnt, 896 + 10); 897 + DEBUG("write_blk_fifo Status = 0x%8x Bytes Transfer = %d Data = 0x%x\n", Status, cnt, *pblk); 898 + 899 + kfree(pblk); 900 + #else 901 + usb_init_urb(ft1000dev->tx_urb); 902 + memcpy (ft1000dev->tx_buf, *pUcFile, byte_length); 903 + usb_fill_bulk_urb(ft1000dev->tx_urb, 904 + ft1000dev->dev, 905 + usb_sndbulkpipe(ft1000dev->dev, ft1000dev->bulk_out_endpointAddr), 906 + ft1000dev->tx_buf, 907 + byte_length, 908 + usb_dnld_complete, 909 + (void*)ft1000dev); 910 + 911 + usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC); 912 + #endif 913 + 914 + *pUsFile = *pUsFile + (word_length << 1); 915 + *pUcFile = *pUcFile + (word_length << 2); 916 + 917 + return Status; 918 + } 919 + 920 + //--------------------------------------------------------------------------- 921 + // 922 + // Function: scram_dnldr 923 + // 924 + // Synopsis: Scramble downloader for Harley based ASIC via USB interface 925 + // 926 + // Arguments: pFileStart - pointer to start of file 927 + // FileLength - file length 928 + // 929 + // Returns: status - return code 930 + //--------------------------------------------------------------------------- 931 + 932 + u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLength) 933 + { 934 + u16 Status = STATUS_SUCCESS; 935 + UINT uiState; 936 + USHORT handshake; 937 + PPSEUDO_HDR pHdr; 938 + USHORT usHdrLength; 939 + //PPROV_RECORD pProvRecord; 940 + PDSP_FILE_HDR pFileHdr; 941 + long word_length; 942 + USHORT request; 943 + USHORT temp; 944 + USHORT tempword; 945 + 946 + PDSP_FILE_HDR_5 pFileHdr5; 947 + PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL; 948 + long requested_version; 949 + BOOLEAN bGoodVersion; 950 + PDRVMSG pMailBoxData; 951 + USHORT *pUsData = NULL; 952 + USHORT *pUsFile = NULL; 953 + UCHAR *pUcFile = NULL; 954 + UCHAR *pBootEnd = NULL, *pCodeEnd= NULL; 955 + int imageN; 956 + long loader_code_address, loader_code_size = 0; 957 + long run_address = 0, run_size = 0; 958 + 959 + ULONG templong; 960 + ULONG image_chksum = 0; 961 + 962 + USHORT dpram = 0; 963 + PUCHAR pbuffer; 964 + PPROV_RECORD pprov_record; 965 + FT1000_INFO *pft1000info = netdev_priv(ft1000dev->net); 966 + 967 + DEBUG("Entered scram_dnldr...\n"); 968 + 969 + pft1000info->fcodeldr = 0; 970 + pft1000info->usbboot = 0; 971 + pft1000info->dspalive = 0xffff; 972 + 973 + 974 + // 975 + // Get version id of file, at first 4 bytes of file, for newer files. 976 + // 977 + 978 + uiState = STATE_START_DWNLD; 979 + 980 + pFileHdr = (PDSP_FILE_HDR)pFileStart; 981 + pFileHdr5 = (PDSP_FILE_HDR_5)pFileStart; 982 + 983 + ft1000_write_register (ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK); 984 + 985 + pUsFile = (USHORT *)(pFileStart + pFileHdr5->loader_offset); 986 + pUcFile = (UCHAR *)(pFileStart + pFileHdr5->loader_offset); 987 + 988 + pBootEnd = (UCHAR *)(pFileStart + pFileHdr5->loader_code_end); 989 + 990 + loader_code_address = pFileHdr5->loader_code_address; 991 + loader_code_size = pFileHdr5->loader_code_size; 992 + bGoodVersion = FALSE; 993 + 994 + while ((Status == STATUS_SUCCESS) && (uiState != STATE_DONE_FILE)) 995 + { 996 + switch (uiState) 997 + { 998 + case STATE_START_DWNLD: 999 + DEBUG("FT1000:STATE_START_DWNLD\n"); 1000 + if (pft1000info->usbboot) 1001 + handshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY); 1002 + else 1003 + handshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY); 1004 + 1005 + if (handshake == HANDSHAKE_DSP_BL_READY) 1006 + { 1007 + DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n"); 1008 + put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY); 1009 + } 1010 + else 1011 + { 1012 + DEBUG("FT1000:download:Download error: Handshake failed\n"); 1013 + Status = STATUS_FAILURE; 1014 + } 1015 + 1016 + uiState = STATE_BOOT_DWNLD; 1017 + 1018 + break; 1019 + 1020 + case STATE_BOOT_DWNLD: 1021 + DEBUG("FT1000:STATE_BOOT_DWNLD\n"); 1022 + pft1000info->bootmode = 1; 1023 + handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST); 1024 + if (handshake == HANDSHAKE_REQUEST) 1025 + { 1026 + /* 1027 + * Get type associated with the request. 1028 + */ 1029 + request = get_request_type(ft1000dev); 1030 + switch (request) 1031 + { 1032 + case REQUEST_RUN_ADDRESS: 1033 + DEBUG("FT1000:REQUEST_RUN_ADDRESS\n"); 1034 + put_request_value(ft1000dev, loader_code_address); 1035 + break; 1036 + case REQUEST_CODE_LENGTH: 1037 + DEBUG("FT1000:REQUEST_CODE_LENGTH\n"); 1038 + put_request_value(ft1000dev, loader_code_size); 1039 + break; 1040 + case REQUEST_DONE_BL: 1041 + DEBUG("FT1000:REQUEST_DONE_BL\n"); 1042 + /* Reposition ptrs to beginning of code section */ 1043 + pUsFile = (USHORT *)(pBootEnd); 1044 + pUcFile = (UCHAR *)(pBootEnd); 1045 + //DEBUG("FT1000:download:pUsFile = 0x%8x\n", (int)pUsFile); 1046 + //DEBUG("FT1000:download:pUcFile = 0x%8x\n", (int)pUcFile); 1047 + uiState = STATE_CODE_DWNLD; 1048 + pft1000info->fcodeldr = 1; 1049 + break; 1050 + case REQUEST_CODE_SEGMENT: 1051 + //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n"); 1052 + word_length = get_request_value(ft1000dev); 1053 + //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length); 1054 + //NdisMSleep (100); 1055 + if (word_length > MAX_LENGTH) 1056 + { 1057 + DEBUG("FT1000:download:Download error: Max length exceeded\n"); 1058 + Status = STATUS_FAILURE; 1059 + break; 1060 + } 1061 + if ( (word_length*2 + pUcFile) > pBootEnd) 1062 + { 1063 + /* 1064 + * Error, beyond boot code range. 1065 + */ 1066 + DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n", 1067 + (int)word_length); 1068 + Status = STATUS_FAILURE; 1069 + break; 1070 + } 1071 + /* 1072 + * Position ASIC DPRAM auto-increment pointer. 1073 + */ 1074 + dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; 1075 + if (word_length & 0x1) 1076 + word_length++; 1077 + word_length = word_length / 2; 1078 + 1079 + Status = write_blk(ft1000dev, &pUsFile, &pUcFile, word_length); 1080 + //DEBUG("write_blk returned %d\n", Status); 1081 + break; 1082 + default: 1083 + DEBUG("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",request); 1084 + Status = STATUS_FAILURE; 1085 + break; 1086 + } 1087 + if (pft1000info->usbboot) 1088 + put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE); 1089 + else 1090 + put_handshake(ft1000dev, HANDSHAKE_RESPONSE); 1091 + } 1092 + else 1093 + { 1094 + DEBUG("FT1000:download:Download error: Handshake failed\n"); 1095 + Status = STATUS_FAILURE; 1096 + } 1097 + 1098 + break; 1099 + 1100 + case STATE_CODE_DWNLD: 1101 + //DEBUG("FT1000:STATE_CODE_DWNLD\n"); 1102 + pft1000info->bootmode = 0; 1103 + if (pft1000info->usbboot) 1104 + handshake = get_handshake_usb(ft1000dev, HANDSHAKE_REQUEST); 1105 + else 1106 + handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST); 1107 + if (handshake == HANDSHAKE_REQUEST) 1108 + { 1109 + /* 1110 + * Get type associated with the request. 1111 + */ 1112 + if (pft1000info->usbboot) 1113 + request = get_request_type_usb(ft1000dev); 1114 + else 1115 + request = get_request_type(ft1000dev); 1116 + switch (request) 1117 + { 1118 + case REQUEST_FILE_CHECKSUM: 1119 + DEBUG("FT1000:download:image_chksum = 0x%8x\n", image_chksum); 1120 + put_request_value(ft1000dev, image_chksum); 1121 + break; 1122 + case REQUEST_RUN_ADDRESS: 1123 + DEBUG("FT1000:download: REQUEST_RUN_ADDRESS\n"); 1124 + if (bGoodVersion) 1125 + { 1126 + DEBUG("FT1000:download:run_address = 0x%8x\n", (int)run_address); 1127 + put_request_value(ft1000dev, run_address); 1128 + } 1129 + else 1130 + { 1131 + DEBUG("FT1000:download:Download error: Got Run address request before image offset request.\n"); 1132 + Status = STATUS_FAILURE; 1133 + break; 1134 + } 1135 + break; 1136 + case REQUEST_CODE_LENGTH: 1137 + DEBUG("FT1000:download:REQUEST_CODE_LENGTH\n"); 1138 + if (bGoodVersion) 1139 + { 1140 + DEBUG("FT1000:download:run_size = 0x%8x\n", (int)run_size); 1141 + put_request_value(ft1000dev, run_size); 1142 + } 1143 + else 1144 + { 1145 + DEBUG("FT1000:download:Download error: Got Size request before image offset request.\n"); 1146 + Status = STATUS_FAILURE; 1147 + break; 1148 + } 1149 + break; 1150 + case REQUEST_DONE_CL: 1151 + #if FIFO_DNLD 1152 + pft1000info->usbboot = 3; 1153 + #endif 1154 + /* Reposition ptrs to beginning of provisioning section */ 1155 + pUsFile = (USHORT *)(pFileStart + pFileHdr5->commands_offset); 1156 + pUcFile = (UCHAR *)(pFileStart + pFileHdr5->commands_offset); 1157 + uiState = STATE_DONE_DWNLD; 1158 + break; 1159 + case REQUEST_CODE_SEGMENT: 1160 + //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); 1161 + if (!bGoodVersion) 1162 + { 1163 + DEBUG("FT1000:download:Download error: Got Code Segment request before image offset request.\n"); 1164 + Status = STATUS_FAILURE; 1165 + break; 1166 + } 1167 + #if 0 1168 + word_length = get_request_value_usb(ft1000dev); 1169 + //DEBUG("FT1000:download:word_length = %d\n", (int)word_length); 1170 + if (word_length > MAX_LENGTH/2) 1171 + #else 1172 + word_length = get_request_value(ft1000dev); 1173 + //DEBUG("FT1000:download:word_length = %d\n", (int)word_length); 1174 + if (word_length > MAX_LENGTH) 1175 + #endif 1176 + { 1177 + DEBUG("FT1000:download:Download error: Max length exceeded\n"); 1178 + Status = STATUS_FAILURE; 1179 + break; 1180 + } 1181 + if ( (word_length*2 + pUcFile) > pCodeEnd) 1182 + { 1183 + /* 1184 + * Error, beyond boot code range. 1185 + */ 1186 + DEBUG("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n", 1187 + (int)word_length); 1188 + Status = STATUS_FAILURE; 1189 + break; 1190 + } 1191 + /* 1192 + * Position ASIC DPRAM auto-increment pointer. 1193 + */ 1194 + dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; 1195 + if (word_length & 0x1) 1196 + word_length++; 1197 + word_length = word_length / 2; 1198 + 1199 + #if FIFO_DNLD 1200 + write_blk_fifo (ft1000dev, &pUsFile, &pUcFile, word_length); 1201 + if (pft1000info->usbboot == 0) 1202 + pft1000info->usbboot++; 1203 + if (pft1000info->usbboot == 1) { 1204 + tempword = 0; 1205 + ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_PS_HDR_LOC, tempword, 0); 1206 + } 1207 + #else 1208 + write_blk (ft1000dev, &pUsFile, &pUcFile, word_length); 1209 + //ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)pUcFile, word_length); 1210 + #endif 1211 + break; 1212 + 1213 + case REQUEST_MAILBOX_DATA: 1214 + DEBUG("FT1000:download: REQUEST_MAILBOX_DATA\n"); 1215 + // Convert length from byte count to word count. Make sure we round up. 1216 + word_length = (long)(pft1000info->DSPInfoBlklen + 1)/2; 1217 + put_request_value(ft1000dev, word_length); 1218 + pMailBoxData = (PDRVMSG)&(pft1000info->DSPInfoBlk[0]); 1219 + /* 1220 + * Position ASIC DPRAM auto-increment pointer. 1221 + */ 1222 + 1223 + 1224 + pUsData = (USHORT *)&pMailBoxData->data[0]; 1225 + dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; 1226 + if (word_length & 0x1) 1227 + word_length++; 1228 + 1229 + word_length = (word_length / 2); 1230 + 1231 + 1232 + for (; word_length > 0; word_length--) /* In words */ 1233 + { 1234 + 1235 + templong = *pUsData++; 1236 + templong |= (*pUsData++ << 16); 1237 + Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (PUCHAR)&templong); 1238 + 1239 + } 1240 + break; 1241 + 1242 + case REQUEST_VERSION_INFO: 1243 + DEBUG("FT1000:download:REQUEST_VERSION_INFO\n"); 1244 + word_length = pFileHdr5->version_data_size; 1245 + put_request_value(ft1000dev, word_length); 1246 + /* 1247 + * Position ASIC DPRAM auto-increment pointer. 1248 + */ 1249 + 1250 + pUsFile = (USHORT *)(pFileStart + pFileHdr5->version_data_offset); 1251 + 1252 + 1253 + dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; 1254 + if (word_length & 0x1) 1255 + word_length++; 1256 + 1257 + word_length = (word_length / 2); 1258 + 1259 + 1260 + for (; word_length > 0; word_length--) /* In words */ 1261 + { 1262 + 1263 + templong = ntohs(*pUsFile++); 1264 + temp = ntohs(*pUsFile++); 1265 + templong |= (temp << 16); 1266 + Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (PUCHAR)&templong); 1267 + 1268 + } 1269 + break; 1270 + 1271 + case REQUEST_CODE_BY_VERSION: 1272 + DEBUG("FT1000:download:REQUEST_CODE_BY_VERSION\n"); 1273 + bGoodVersion = FALSE; 1274 + requested_version = get_request_value(ft1000dev); 1275 + 1276 + pDspImageInfoV6 = (PDSP_IMAGE_INFO_V6)(pFileStart + sizeof(DSP_FILE_HDR_5)); 1277 + 1278 + for (imageN = 0; imageN < pFileHdr5->nDspImages; imageN++) 1279 + { 1280 + 1281 + temp = (USHORT)(pDspImageInfoV6->version); 1282 + templong = temp; 1283 + temp = (USHORT)(pDspImageInfoV6->version >> 16); 1284 + templong |= (temp << 16); 1285 + if (templong == (ULONG)requested_version) 1286 + { 1287 + bGoodVersion = TRUE; 1288 + DEBUG("FT1000:download: bGoodVersion is TRUE\n"); 1289 + pUsFile = (USHORT *)(pFileStart + pDspImageInfoV6->begin_offset); 1290 + pUcFile = (UCHAR *)(pFileStart + pDspImageInfoV6->begin_offset); 1291 + pCodeEnd = (UCHAR *)(pFileStart + pDspImageInfoV6->end_offset); 1292 + run_address = pDspImageInfoV6->run_address; 1293 + run_size = pDspImageInfoV6->image_size; 1294 + image_chksum = (ULONG)pDspImageInfoV6->checksum; 1295 + break; 1296 + } 1297 + pDspImageInfoV6++; 1298 + 1299 + 1300 + } //end of for 1301 + 1302 + if (!bGoodVersion) 1303 + { 1304 + /* 1305 + * Error, beyond boot code range. 1306 + */ 1307 + DEBUG("FT1000:download:Download error: Bad Version Request = 0x%x.\n",(int)requested_version); 1308 + Status = STATUS_FAILURE; 1309 + break; 1310 + } 1311 + break; 1312 + 1313 + default: 1314 + DEBUG("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",request); 1315 + Status = STATUS_FAILURE; 1316 + break; 1317 + } 1318 + if (pft1000info->usbboot) 1319 + put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE); 1320 + else 1321 + put_handshake(ft1000dev, HANDSHAKE_RESPONSE); 1322 + } 1323 + else 1324 + { 1325 + DEBUG("FT1000:download:Download error: Handshake failed\n"); 1326 + Status = STATUS_FAILURE; 1327 + } 1328 + 1329 + break; 1330 + 1331 + case STATE_DONE_DWNLD: 1332 + DEBUG("FT1000:download:Code loader is done...\n"); 1333 + uiState = STATE_SECTION_PROV; 1334 + break; 1335 + 1336 + case STATE_SECTION_PROV: 1337 + DEBUG("FT1000:download:STATE_SECTION_PROV\n"); 1338 + pHdr = (PPSEUDO_HDR)pUcFile; 1339 + 1340 + if (pHdr->checksum == hdr_checksum(pHdr)) 1341 + { 1342 + if (pHdr->portdest != 0x80 /* Dsp OAM */) 1343 + { 1344 + uiState = STATE_DONE_PROV; 1345 + break; 1346 + } 1347 + usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */ 1348 + 1349 + // Get buffer for provisioning data 1350 + pbuffer = kmalloc ( (usHdrLength + sizeof(PSEUDO_HDR) ), GFP_ATOMIC ); 1351 + if (pbuffer) { 1352 + memcpy(pbuffer, (void *)pUcFile, (UINT)(usHdrLength + sizeof(PSEUDO_HDR))); 1353 + // link provisioning data 1354 + pprov_record = kmalloc( sizeof(PROV_RECORD), GFP_ATOMIC ); 1355 + if (pprov_record) { 1356 + pprov_record->pprov_data = pbuffer; 1357 + list_add_tail (&pprov_record->list, &pft1000info->prov_list); 1358 + // Move to next entry if available 1359 + pUcFile = (UCHAR *)((UINT)pUcFile + (UINT)((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR)); 1360 + if ( (UINT)(pUcFile) - (UINT)(pFileStart) >= (UINT)FileLength) { 1361 + uiState = STATE_DONE_FILE; 1362 + } 1363 + } 1364 + else { 1365 + kfree(pbuffer); 1366 + Status = STATUS_FAILURE; 1367 + } 1368 + } 1369 + else { 1370 + Status = STATUS_FAILURE; 1371 + } 1372 + } 1373 + else 1374 + { 1375 + /* Checksum did not compute */ 1376 + Status = STATUS_FAILURE; 1377 + } 1378 + DEBUG("ft1000:download: after STATE_SECTION_PROV, uiState = %d, Status= %d\n", uiState, Status); 1379 + break; 1380 + 1381 + case STATE_DONE_PROV: 1382 + DEBUG("FT1000:download:STATE_DONE_PROV\n"); 1383 + uiState = STATE_DONE_FILE; 1384 + break; 1385 + 1386 + 1387 + default: 1388 + Status = STATUS_FAILURE; 1389 + break; 1390 + } /* End Switch */ 1391 + 1392 + if (Status != STATUS_SUCCESS) { 1393 + break; 1394 + } 1395 + 1396 + /**** 1397 + // Check if Card is present 1398 + Status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK); 1399 + if ( (Status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) { 1400 + break; 1401 + } 1402 + 1403 + Status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID); 1404 + if ( (Status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) { 1405 + break; 1406 + } 1407 + ****/ 1408 + 1409 + } /* End while */ 1410 + 1411 + DEBUG("Download exiting with status = 0x%8x\n", Status); 1412 + ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL); 1413 + 1414 + return Status; 1415 + } 1416 +
+2762
drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
··· 1 + //===================================================== 2 + // CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. 3 + // 4 + // 5 + // This file is part of Express Card USB Driver 6 + // 7 + // $Id: 8 + //==================================================== 9 + // 20090926; aelias; removed compiler warnings & errors; ubuntu 9.04; 2.6.28-15-generic 10 + 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/netdevice.h> 15 + #include <linux/etherdevice.h> 16 + #include <linux/usb.h> 17 + #include "ft1000_usb.h" 18 + #include <linux/types.h> 19 + //#include <asm/semaphore.h> //aelias [-] reason : file moved 20 + //#include <linux/semaphore.h> //aelias [+] reason : file moved 21 + //#include <asm/io.h> 22 + //#include <linux/kthread.h> 23 + 24 + #define HARLEY_READ_REGISTER 0x0 25 + #define HARLEY_WRITE_REGISTER 0x01 26 + #define HARLEY_READ_DPRAM_32 0x02 27 + #define HARLEY_READ_DPRAM_LOW 0x03 28 + #define HARLEY_READ_DPRAM_HIGH 0x04 29 + #define HARLEY_WRITE_DPRAM_32 0x05 30 + #define HARLEY_WRITE_DPRAM_LOW 0x06 31 + #define HARLEY_WRITE_DPRAM_HIGH 0x07 32 + 33 + #define HARLEY_READ_OPERATION 0xc1 34 + #define HARLEY_WRITE_OPERATION 0x41 35 + 36 + //#define JDEBUG 37 + 38 + 39 + extern void *pFileStart; 40 + extern ULONG FileLength; 41 + 42 + 43 + extern int numofmsgbuf; 44 + 45 + 46 + int ft1000_poll_thread(void *arg); 47 + 48 + static void ft1000_hbchk(u_long data); 49 + int ft1000_reset(struct net_device *ft1000dev); 50 + static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev); 51 + static int ft1000_open (struct net_device *dev); 52 + int ft1000_close (struct net_device *dev); 53 + static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev); 54 + u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLength); 55 + int ft1000_submit_rx_urb(PFT1000_INFO info); 56 + static struct timer_list poll_timer[MAX_NUM_CARDS]; 57 + static int ft1000_chkcard (struct ft1000_device *dev); 58 + /* 59 + static const struct net_device_ops ft1000net_ops = { 60 + .ndo_start_xmit = ft1000_start_xmit, 61 + .ndo_get_stats = ft1000_netdev_stats, 62 + .ndo_open = ft1000_open, 63 + .ndo_stop = ft1000_close, 64 + }; 65 + */ 66 + 67 + //Jim 68 + 69 + static u8 tempbuffer[1600]; 70 + int gCardIndex; 71 + 72 + #define MAX_RCV_LOOP 100 73 + 74 + 75 + extern struct list_head freercvpool; 76 + extern spinlock_t free_buff_lock; // lock to arbitrate free buffer list for receive command data 77 + 78 + //end of Jim 79 + 80 + extern int ft1000_CreateDevice(struct ft1000_device *dev); 81 + extern PDPRAM_BLK ft1000_get_buffer (struct list_head *bufflist); 82 + extern void ft1000_free_buffer (PDPRAM_BLK pdpram_blk, struct list_head *plist); 83 + 84 + 85 + static int atoi(const char *s) 86 + { 87 + int k = 0; 88 + int cnt; 89 + 90 + k = 0; 91 + cnt = 0; 92 + while (*s != '\0' && *s >= '0' && *s <= '9') { 93 + k = 10 * k + (*s - '0'); 94 + s++; 95 + // Let's put a limit on this while loop to avoid deadlock scenario 96 + if (cnt > 100) 97 + break; 98 + cnt++; 99 + } 100 + return k; 101 + } 102 + /**************************************************************** 103 + * ft1000_control_complete 104 + ****************************************************************/ 105 + static void ft1000_control_complete(struct urb *urb) 106 + { 107 + struct ft1000_device *ft1000dev = (struct ft1000_device *)urb->context; 108 + 109 + //DEBUG("FT1000_CONTROL_COMPLETE ENTERED\n"); 110 + if (ft1000dev == NULL ) 111 + { 112 + DEBUG("NULL ft1000dev, failure\n"); 113 + return ; 114 + } 115 + else if ( ft1000dev->dev == NULL ) 116 + { 117 + DEBUG("NULL ft1000dev->dev, failure\n"); 118 + return ; 119 + } 120 + //spin_lock(&ft1000dev->device_lock); 121 + 122 + if(waitqueue_active(&ft1000dev->control_wait)) 123 + { 124 + wake_up(&ft1000dev->control_wait); 125 + } 126 + 127 + //DEBUG("FT1000_CONTROL_COMPLETE RETURNED\n"); 128 + //spin_unlock(&ft1000dev->device_lock); 129 + } 130 + 131 + //--------------------------------------------------------------------------- 132 + // Function: ft1000_control 133 + // 134 + // Parameters: ft1000_device - device structure 135 + // pipe - usb control message pipe 136 + // request - control request 137 + // requesttype - control message request type 138 + // value - value to be written or 0 139 + // index - register index 140 + // data - data buffer to hold the read/write values 141 + // size - data size 142 + // timeout - control message time out value 143 + // 144 + // Returns: STATUS_SUCCESS - success 145 + // STATUS_FAILURE - failure 146 + // 147 + // Description: This function sends a control message via USB interface synchronously 148 + // 149 + // Notes: 150 + // 151 + //--------------------------------------------------------------------------- 152 + static int ft1000_control(struct ft1000_device *ft1000dev,unsigned int pipe, 153 + u8 request, 154 + u8 requesttype, 155 + u16 value, 156 + u16 index, 157 + void *data, 158 + u16 size, 159 + int timeout) 160 + { 161 + u16 ret; 162 + 163 + if (ft1000dev == NULL ) 164 + { 165 + DEBUG("NULL ft1000dev, failure\n"); 166 + return STATUS_FAILURE; 167 + } 168 + else if ( ft1000dev->dev == NULL ) 169 + { 170 + DEBUG("NULL ft1000dev->dev, failure\n"); 171 + return STATUS_FAILURE; 172 + } 173 + 174 + ret = usb_control_msg(ft1000dev->dev, 175 + pipe, 176 + request, 177 + requesttype, 178 + value, 179 + index, 180 + data, 181 + size, 182 + LARGE_TIMEOUT); 183 + 184 + if (ret>0) 185 + ret = STATUS_SUCCESS; 186 + else 187 + ret = STATUS_FAILURE; 188 + 189 + 190 + return ret; 191 + 192 + 193 + } 194 + //--------------------------------------------------------------------------- 195 + // Function: ft1000_read_register 196 + // 197 + // Parameters: ft1000_device - device structure 198 + // Data - data buffer to hold the value read 199 + // nRegIndex - register index 200 + // 201 + // Returns: STATUS_SUCCESS - success 202 + // STATUS_FAILURE - failure 203 + // 204 + // Description: This function returns the value in a register 205 + // 206 + // Notes: 207 + // 208 + //--------------------------------------------------------------------------- 209 + 210 + u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx) 211 + { 212 + u16 ret = STATUS_SUCCESS; 213 + 214 + //DEBUG("ft1000_read_register: reg index is %d\n", nRegIndx); 215 + //DEBUG("ft1000_read_register: spin_lock locked\n"); 216 + ret = ft1000_control(ft1000dev, 217 + usb_rcvctrlpipe(ft1000dev->dev,0), 218 + HARLEY_READ_REGISTER, //request --READ_REGISTER 219 + HARLEY_READ_OPERATION, //requestType 220 + 0, //value 221 + nRegIndx, //index 222 + Data, //data 223 + 2, //data size 224 + LARGE_TIMEOUT ); //timeout 225 + 226 + //DEBUG("ft1000_read_register: ret is %d \n", ret); 227 + 228 + //DEBUG("ft1000_read_register: data is %x \n", *Data); 229 + if ( ret != STATUS_SUCCESS ) 230 + return STATUS_FAILURE; 231 + 232 + return ret; 233 + 234 + } 235 + 236 + //--------------------------------------------------------------------------- 237 + // Function: ft1000_write_register 238 + // 239 + // Parameters: ft1000_device - device structure 240 + // value - value to write into a register 241 + // nRegIndex - register index 242 + // 243 + // Returns: STATUS_SUCCESS - success 244 + // STATUS_FAILURE - failure 245 + // 246 + // Description: This function writes the value in a register 247 + // 248 + // Notes: 249 + // 250 + //--------------------------------------------------------------------------- 251 + u16 ft1000_write_register(struct ft1000_device *ft1000dev, USHORT value, u16 nRegIndx) 252 + { 253 + u16 ret = STATUS_SUCCESS; 254 + 255 + //DEBUG("ft1000_write_register: value is: %d, reg index is: %d\n", value, nRegIndx); 256 + 257 + ret = ft1000_control(ft1000dev, 258 + usb_sndctrlpipe(ft1000dev->dev, 0), 259 + HARLEY_WRITE_REGISTER, //request -- WRITE_REGISTER 260 + HARLEY_WRITE_OPERATION, //requestType 261 + value, 262 + nRegIndx, 263 + NULL, 264 + 0, 265 + LARGE_TIMEOUT ); 266 + 267 + if ( ret != STATUS_SUCCESS ) 268 + return STATUS_FAILURE; 269 + 270 + return ret; 271 + } 272 + 273 + //--------------------------------------------------------------------------- 274 + // Function: ft1000_read_dpram32 275 + // 276 + // Parameters: ft1000_device - device structure 277 + // indx - starting address to read 278 + // buffer - data buffer to hold the data read 279 + // cnt - number of byte read from DPRAM 280 + // 281 + // Returns: STATUS_SUCCESS - success 282 + // STATUS_FAILURE - failure 283 + // 284 + // Description: This function read a number of bytes from DPRAM 285 + // 286 + // Notes: 287 + // 288 + //--------------------------------------------------------------------------- 289 + 290 + u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt) 291 + { 292 + u16 ret = STATUS_SUCCESS; 293 + 294 + //DEBUG("ft1000_read_dpram32: indx: %d cnt: %d\n", indx, cnt); 295 + ret =ft1000_control(ft1000dev, 296 + usb_rcvctrlpipe(ft1000dev->dev,0), 297 + HARLEY_READ_DPRAM_32, //request --READ_DPRAM_32 298 + HARLEY_READ_OPERATION, //requestType 299 + 0, //value 300 + indx, //index 301 + buffer, //data 302 + cnt, //data size 303 + LARGE_TIMEOUT ); //timeout 304 + 305 + //DEBUG("ft1000_read_dpram32: ret is %d \n", ret); 306 + 307 + //DEBUG("ft1000_read_dpram32: ret=%d \n", ret); 308 + if ( ret != STATUS_SUCCESS ) 309 + return STATUS_FAILURE; 310 + 311 + return ret; 312 + 313 + } 314 + 315 + //--------------------------------------------------------------------------- 316 + // Function: ft1000_write_dpram32 317 + // 318 + // Parameters: ft1000_device - device structure 319 + // indx - starting address to write the data 320 + // buffer - data buffer to write into DPRAM 321 + // cnt - number of bytes to write 322 + // 323 + // Returns: STATUS_SUCCESS - success 324 + // STATUS_FAILURE - failure 325 + // 326 + // Description: This function writes into DPRAM a number of bytes 327 + // 328 + // Notes: 329 + // 330 + //--------------------------------------------------------------------------- 331 + u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt) 332 + { 333 + u16 ret = STATUS_SUCCESS; 334 + 335 + //DEBUG("ft1000_write_dpram32: indx: %d buffer: %x cnt: %d\n", indx, buffer, cnt); 336 + if ( cnt % 4) 337 + cnt += cnt - (cnt % 4); 338 + 339 + ret = ft1000_control(ft1000dev, 340 + usb_sndctrlpipe(ft1000dev->dev, 0), 341 + HARLEY_WRITE_DPRAM_32, //request -- WRITE_DPRAM_32 342 + HARLEY_WRITE_OPERATION, //requestType 343 + 0, //value 344 + indx, //index 345 + buffer, //buffer 346 + cnt, //buffer size 347 + LARGE_TIMEOUT ); 348 + 349 + 350 + if ( ret != STATUS_SUCCESS ) 351 + return STATUS_FAILURE; 352 + 353 + 354 + return ret; 355 + } 356 + 357 + //--------------------------------------------------------------------------- 358 + // Function: ft1000_read_dpram16 359 + // 360 + // Parameters: ft1000_device - device structure 361 + // indx - starting address to read 362 + // buffer - data buffer to hold the data read 363 + // hightlow - high or low 16 bit word 364 + // 365 + // Returns: STATUS_SUCCESS - success 366 + // STATUS_FAILURE - failure 367 + // 368 + // Description: This function read 16 bits from DPRAM 369 + // 370 + // Notes: 371 + // 372 + //--------------------------------------------------------------------------- 373 + u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow) 374 + { 375 + u16 ret = STATUS_SUCCESS; 376 + 377 + //DEBUG("ft1000_read_dpram16: indx: %d hightlow: %d\n", indx, highlow); 378 + 379 + u8 request; 380 + 381 + if (highlow == 0 ) 382 + request = HARLEY_READ_DPRAM_LOW; 383 + else 384 + request = HARLEY_READ_DPRAM_HIGH; 385 + 386 + ret = ft1000_control(ft1000dev, 387 + usb_rcvctrlpipe(ft1000dev->dev,0), 388 + request, //request --READ_DPRAM_H/L 389 + HARLEY_READ_OPERATION, //requestType 390 + 0, //value 391 + indx, //index 392 + buffer, //data 393 + 2, //data size 394 + LARGE_TIMEOUT ); //timeout 395 + 396 + //DEBUG("ft1000_read_dpram16: ret is %d \n", ret); 397 + 398 + 399 + //DEBUG("ft1000_read_dpram16: data is %x \n", *buffer); 400 + if ( ret != STATUS_SUCCESS ) 401 + return STATUS_FAILURE; 402 + 403 + return ret; 404 + 405 + } 406 + 407 + //--------------------------------------------------------------------------- 408 + // Function: ft1000_write_dpram16 409 + // 410 + // Parameters: ft1000_device - device structure 411 + // indx - starting address to write the data 412 + // value - 16bits value to write 413 + // hightlow - high or low 16 bit word 414 + // 415 + // Returns: STATUS_SUCCESS - success 416 + // STATUS_FAILURE - failure 417 + // 418 + // Description: This function writes into DPRAM a number of bytes 419 + // 420 + // Notes: 421 + // 422 + //--------------------------------------------------------------------------- 423 + u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, USHORT indx, USHORT value, u8 highlow) 424 + { 425 + u16 ret = STATUS_SUCCESS; 426 + 427 + 428 + 429 + //DEBUG("ft1000_write_dpram16: indx: %d value: %d highlow: %d\n", indx, value, highlow); 430 + 431 + u8 request; 432 + 433 + 434 + if ( highlow == 0 ) 435 + request = HARLEY_WRITE_DPRAM_LOW; 436 + else 437 + request = HARLEY_WRITE_DPRAM_HIGH; 438 + 439 + ret = ft1000_control(ft1000dev, 440 + usb_sndctrlpipe(ft1000dev->dev, 0), 441 + request, //request -- WRITE_DPRAM_H/L 442 + HARLEY_WRITE_OPERATION, //requestType 443 + value, //value 444 + indx, //index 445 + NULL, //buffer 446 + 0, //buffer size 447 + LARGE_TIMEOUT ); 448 + 449 + 450 + if ( ret != STATUS_SUCCESS ) 451 + return STATUS_FAILURE; 452 + 453 + 454 + return ret; 455 + } 456 + 457 + //--------------------------------------------------------------------------- 458 + // Function: fix_ft1000_read_dpram32 459 + // 460 + // Parameters: ft1000_device - device structure 461 + // indx - starting address to read 462 + // buffer - data buffer to hold the data read 463 + // 464 + // 465 + // Returns: STATUS_SUCCESS - success 466 + // STATUS_FAILURE - failure 467 + // 468 + // Description: This function read DPRAM 4 words at a time 469 + // 470 + // Notes: 471 + // 472 + //--------------------------------------------------------------------------- 473 + u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer) 474 + { 475 + UCHAR tempbuffer[16]; 476 + USHORT pos; 477 + u16 ret = STATUS_SUCCESS; 478 + 479 + //DEBUG("fix_ft1000_read_dpram32: indx: %d \n", indx); 480 + pos = (indx / 4)*4; 481 + ret = ft1000_read_dpram32(ft1000dev, pos, (PUCHAR)&tempbuffer[0], 16); 482 + if (ret == STATUS_SUCCESS) 483 + { 484 + pos = (indx % 4)*4; 485 + *buffer++ = tempbuffer[pos++]; 486 + *buffer++ = tempbuffer[pos++]; 487 + *buffer++ = tempbuffer[pos++]; 488 + *buffer++ = tempbuffer[pos++]; 489 + } 490 + else 491 + { 492 + DEBUG("fix_ft1000_read_dpram32: DPRAM32 Read failed\n"); 493 + *buffer++ = 0; 494 + *buffer++ = 0; 495 + *buffer++ = 0; 496 + *buffer++ = 0; 497 + 498 + } 499 + 500 + //DEBUG("fix_ft1000_read_dpram32: data is %x \n", *buffer); 501 + return ret; 502 + 503 + } 504 + 505 + 506 + //--------------------------------------------------------------------------- 507 + // Function: fix_ft1000_write_dpram32 508 + // 509 + // Parameters: ft1000_device - device structure 510 + // indx - starting address to write 511 + // buffer - data buffer to write 512 + // 513 + // 514 + // Returns: STATUS_SUCCESS - success 515 + // STATUS_FAILURE - failure 516 + // 517 + // Description: This function write to DPRAM 4 words at a time 518 + // 519 + // Notes: 520 + // 521 + //--------------------------------------------------------------------------- 522 + u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer) 523 + { 524 + USHORT pos1; 525 + USHORT pos2; 526 + USHORT i; 527 + UCHAR tempbuffer[32]; 528 + UCHAR resultbuffer[32]; 529 + PUCHAR pdata; 530 + u16 ret = STATUS_SUCCESS; 531 + 532 + //DEBUG("fix_ft1000_write_dpram32: Entered:\n"); 533 + 534 + pos1 = (indx / 4)*4; 535 + pdata = buffer; 536 + ret = ft1000_read_dpram32(ft1000dev, pos1, (PUCHAR)&tempbuffer[0], 16); 537 + if (ret == STATUS_SUCCESS) 538 + { 539 + pos2 = (indx % 4)*4; 540 + tempbuffer[pos2++] = *buffer++; 541 + tempbuffer[pos2++] = *buffer++; 542 + tempbuffer[pos2++] = *buffer++; 543 + tempbuffer[pos2++] = *buffer++; 544 + ret = ft1000_write_dpram32(ft1000dev, pos1, (PUCHAR)&tempbuffer[0], 16); 545 + } 546 + else 547 + { 548 + DEBUG("fix_ft1000_write_dpram32: DPRAM32 Read failed\n"); 549 + 550 + return ret; 551 + } 552 + 553 + ret = ft1000_read_dpram32(ft1000dev, pos1, (PUCHAR)&resultbuffer[0], 16); 554 + if (ret == STATUS_SUCCESS) 555 + { 556 + buffer = pdata; 557 + for (i=0; i<16; i++) 558 + { 559 + if (tempbuffer[i] != resultbuffer[i]){ 560 + 561 + ret = STATUS_FAILURE; 562 + } 563 + } 564 + } 565 + 566 + if (ret == STATUS_FAILURE) 567 + { 568 + ret = ft1000_write_dpram32(ft1000dev, pos1, (PUCHAR)&tempbuffer[0], 16); 569 + ret = ft1000_read_dpram32(ft1000dev, pos1, (PUCHAR)&resultbuffer[0], 16); 570 + if (ret == STATUS_SUCCESS) 571 + { 572 + buffer = pdata; 573 + for (i=0; i<16; i++) 574 + { 575 + if (tempbuffer[i] != resultbuffer[i]) 576 + { 577 + ret = STATUS_FAILURE; 578 + DEBUG("fix_ft1000_write_dpram32 Failed to write\n"); 579 + } 580 + } 581 + } 582 + } 583 + 584 + return ret; 585 + 586 + } 587 + 588 + 589 + //------------------------------------------------------------------------ 590 + // 591 + // Function: card_reset_dsp 592 + // 593 + // Synopsis: This function is called to reset or activate the DSP 594 + // 595 + // Arguments: value - reset or activate 596 + // 597 + // Returns: None 598 + //----------------------------------------------------------------------- 599 + void card_reset_dsp (struct ft1000_device *ft1000dev, BOOLEAN value) 600 + { 601 + u16 status = STATUS_SUCCESS; 602 + USHORT tempword; 603 + 604 + status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); 605 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_CTRL); 606 + if (value) 607 + { 608 + DEBUG("Reset DSP\n"); 609 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET); 610 + tempword |= DSP_RESET_BIT; 611 + status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 612 + } 613 + else 614 + { 615 + DEBUG("Activate DSP\n"); 616 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET); 617 + #if 1 618 + tempword |= DSP_ENCRYPTED; 619 + tempword &= ~DSP_UNENCRYPTED; 620 + #else 621 + tempword |= DSP_UNENCRYPTED; 622 + tempword &= ~DSP_ENCRYPTED; 623 + #endif 624 + status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 625 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET); 626 + tempword &= ~EFUSE_MEM_DISABLE; 627 + tempword &= ~DSP_RESET_BIT; 628 + status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 629 + status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET); 630 + } 631 + } 632 + 633 + //--------------------------------------------------------------------------- 634 + // Function: CardSendCommand 635 + // 636 + // Parameters: ft1000_device - device structure 637 + // ptempbuffer - command buffer 638 + // size - command buffer size 639 + // 640 + // Returns: STATUS_SUCCESS - success 641 + // STATUS_FAILURE - failure 642 + // 643 + // Description: This function sends a command to ASIC 644 + // 645 + // Notes: 646 + // 647 + //--------------------------------------------------------------------------- 648 + void CardSendCommand(struct ft1000_device *ft1000dev, unsigned char *ptempbuffer, int size) 649 + { 650 + unsigned short temp; 651 + unsigned char *commandbuf; 652 + 653 + DEBUG("CardSendCommand: enter CardSendCommand... size=%d\n", size); 654 + 655 + commandbuf =(unsigned char*) kmalloc(size+2, GFP_KERNEL); 656 + //memset((void*)commandbuf, 0, size+2); 657 + memcpy((void*)commandbuf+2, (void*)ptempbuffer, size); 658 + 659 + //DEBUG("CardSendCommand: Command Send\n"); 660 + /*** 661 + for (i=0; i<size+2; i++) 662 + { 663 + DEBUG("FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++); 664 + } 665 + ***/ 666 + 667 + ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); 668 + 669 + if (temp & 0x0100) 670 + { 671 + msleep(10); 672 + } 673 + 674 + // check for odd word 675 + size = size + 2; 676 + if (size % 4) 677 + { 678 + // Must force to be 32 bit aligned 679 + size += 4 - (size % 4); 680 + } 681 + 682 + 683 + //DEBUG("CardSendCommand: write dpram ... size=%d\n", size); 684 + ft1000_write_dpram32(ft1000dev, 0,commandbuf, size); 685 + msleep(1); 686 + //DEBUG("CardSendCommand: write into doorbell ...\n"); 687 + ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX ,FT1000_REG_DOORBELL) ; 688 + msleep(1); 689 + 690 + ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); 691 + //DEBUG("CardSendCommand: read doorbell ...temp=%x\n", temp); 692 + if ( (temp & 0x0100) == 0) 693 + { 694 + //DEBUG("CardSendCommand: Message sent\n"); 695 + } 696 + 697 + } 698 + 699 + 700 + //-------------------------------------------------------------------------- 701 + // 702 + // Function: dsp_reload 703 + // 704 + // Synopsis: This function is called to load or reload the DSP 705 + // 706 + // Arguments: ft1000dev - device structure 707 + // 708 + // Returns: None 709 + //----------------------------------------------------------------------- 710 + void dsp_reload (struct ft1000_device *ft1000dev) 711 + { 712 + u16 status; 713 + USHORT tempword; 714 + ULONG templong; 715 + 716 + PFT1000_INFO pft1000info; 717 + 718 + pft1000info = netdev_priv(ft1000dev->net); 719 + 720 + pft1000info->CardReady = 0; 721 + pft1000info->DSP_loading= 1; 722 + 723 + // Program Interrupt Mask register 724 + status = ft1000_write_register (ft1000dev, 0xffff, FT1000_REG_SUP_IMASK); 725 + 726 + status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_RESET); 727 + tempword |= ASIC_RESET_BIT; 728 + status = ft1000_write_register (ft1000dev, tempword, FT1000_REG_RESET); 729 + msleep(1000); 730 + status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_RESET); 731 + DEBUG("Reset Register = 0x%x\n", tempword); 732 + 733 + // Toggle DSP reset 734 + card_reset_dsp (ft1000dev, 1); 735 + msleep(1000); 736 + card_reset_dsp (ft1000dev, 0); 737 + msleep(1000); 738 + 739 + status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); 740 + 741 + // Let's check for FEFE 742 + status = ft1000_read_dpram32 (ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX, (PUCHAR)&templong, 4); 743 + DEBUG("templong (fefe) = 0x%8x\n", templong); 744 + 745 + // call codeloader 746 + status = scram_dnldr(ft1000dev, pFileStart, FileLength); 747 + 748 + if ( status != STATUS_SUCCESS) 749 + return; 750 + 751 + msleep(1000); 752 + pft1000info->DSP_loading= 0; 753 + 754 + DEBUG("dsp_reload returned\n"); 755 + 756 + 757 + } 758 + 759 + //--------------------------------------------------------------------------- 760 + // 761 + // Function: ft1000_reset_asic 762 + // Descripton: This function will call the Card Service function to reset the 763 + // ASIC. 764 + // Input: 765 + // dev - device structure 766 + // Output: 767 + // none 768 + // 769 + //--------------------------------------------------------------------------- 770 + static void ft1000_reset_asic (struct net_device *dev) 771 + { 772 + FT1000_INFO *info = netdev_priv(dev); 773 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 774 + u16 tempword; 775 + 776 + DEBUG("ft1000_hw:ft1000_reset_asic called\n"); 777 + 778 + info->ASICResetNum++; 779 + 780 + // Let's use the register provided by the Magnemite ASIC to reset the 781 + // ASIC and DSP. 782 + ft1000_write_register(ft1000dev, (DSP_RESET_BIT | ASIC_RESET_BIT), FT1000_REG_RESET ); 783 + 784 + mdelay(1); 785 + 786 + // set watermark to -1 in order to not generate an interrrupt 787 + ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_MAG_WATERMARK); 788 + 789 + // clear interrupts 790 + ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_ISR); 791 + DEBUG("ft1000_hw: interrupt status register = 0x%x\n",tempword); 792 + ft1000_write_register (ft1000dev, tempword, FT1000_REG_SUP_ISR); 793 + ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_ISR); 794 + DEBUG("ft1000_hw: interrupt status register = 0x%x\n",tempword); 795 + 796 + } 797 + /* 798 + //--------------------------------------------------------------------------- 799 + // 800 + // Function: ft1000_disable_interrupts 801 + // Descripton: This function will disable all interrupts. 802 + // Input: 803 + // dev - device structure 804 + // Output: 805 + // None. 806 + // 807 + //--------------------------------------------------------------------------- 808 + static void ft1000_disable_interrupts(struct net_device *dev) { 809 + FT1000_INFO *info = netdev_priv(dev); 810 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 811 + u16 tempword; 812 + 813 + DEBUG("ft1000_hw: ft1000_disable_interrupts()\n"); 814 + ft1000_write_register (ft1000dev, ISR_MASK_ALL, FT1000_REG_SUP_IMASK); 815 + ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_IMASK); 816 + DEBUG("ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n", tempword); 817 + info->InterruptsEnabled = FALSE; 818 + } 819 + 820 + //--------------------------------------------------------------------------- 821 + // 822 + // Function: ft1000_enable_interrupts 823 + // Descripton: This function will enable interrupts base on the current interrupt mask. 824 + // Input: 825 + // dev - device structure 826 + // Output: 827 + // None. 828 + // 829 + //--------------------------------------------------------------------------- 830 + static void ft1000_enable_interrupts(struct net_device *dev) { 831 + FT1000_INFO *info = netdev_priv(dev); 832 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 833 + u16 tempword; 834 + 835 + DEBUG("ft1000_hw:ft1000_enable_interrupts()\n"); 836 + ft1000_write_register (ft1000dev, info->CurrentInterruptEnableMask, FT1000_REG_SUP_IMASK); 837 + ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_IMASK); 838 + DEBUG("ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n", tempword); 839 + info->InterruptsEnabled = TRUE; 840 + } 841 + */ 842 + 843 + //--------------------------------------------------------------------------- 844 + // 845 + // Function: ft1000_reset_card 846 + // Descripton: This function will reset the card 847 + // Input: 848 + // dev - device structure 849 + // Output: 850 + // status - FALSE (card reset fail) 851 + // TRUE (card reset successful) 852 + // 853 + //--------------------------------------------------------------------------- 854 + static int ft1000_reset_card (struct net_device *dev) 855 + { 856 + FT1000_INFO *info = netdev_priv(dev); 857 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 858 + u16 tempword; 859 + PPROV_RECORD ptr; 860 + 861 + DEBUG("ft1000_hw:ft1000_reset_card called.....\n"); 862 + 863 + info->fCondResetPend = 1; 864 + info->CardReady = 0; 865 + info->fProvComplete = 0; 866 + //ft1000_disable_interrupts(dev); 867 + 868 + // Cancel heartbeat task since we are reloading the dsp 869 + //del_timer(&poll_timer[info->CardNumber]); 870 + 871 + // Make sure we free any memory reserve for provisioning 872 + while (list_empty(&info->prov_list) == 0) { 873 + DEBUG("ft1000_hw:ft1000_reset_card:deleting provisioning record\n"); 874 + ptr = list_entry(info->prov_list.next, PROV_RECORD, list); 875 + list_del(&ptr->list); 876 + kfree(ptr->pprov_data); 877 + kfree(ptr); 878 + } 879 + 880 + DEBUG("ft1000_hw:ft1000_reset_card: reset asic\n"); 881 + //reset ASIC 882 + ft1000_reset_asic(dev); 883 + 884 + info->DSPResetNum++; 885 + 886 + #if 0 887 + DEBUG("ft1000_hw:ft1000_reset_card:resetting ASIC and DSP\n"); 888 + ft1000_write_register (ft1000dev, (DSP_RESET_BIT | ASIC_RESET_BIT), FT1000_REG_RESET ); 889 + 890 + 891 + // Copy DSP session record into info block if this is not a coldstart 892 + //if (ft1000_card_present == 1) { 893 + spin_lock_irqsave(&info->dpram_lock, flags); 894 + 895 + ft1000_write_register(ft1000dev, FT1000_DPRAM_MAG_RX_BASE, FT1000_REG_DPRAM_ADDR); 896 + for (i=0;i<MAX_DSP_SESS_REC/2; i++) { 897 + //info->DSPSess.MagRec[i] = inl(dev->base_addr+FT1000_REG_MAG_DPDATA); 898 + ft1000_read_dpram32(ft1000dev, FT1000_REG_MAG_DPDATA, (PCHAR)&(info->DSPSess.MagRec[i]), 4); 899 + } 900 + 901 + spin_unlock_irqrestore(&info->dpram_lock, flags); 902 + //} 903 + info->squeseqnum = 0; 904 + 905 + DEBUG("ft1000_hw:ft1000_reset_card:resetting ASIC\n"); 906 + mdelay(10); 907 + //reset ASIC 908 + ft1000_reset_asic(dev); 909 + 910 + info->DSPResetNum++; 911 + 912 + DEBUG("ft1000_hw:ft1000_reset_card:downloading dsp image\n"); 913 + 914 + 915 + // Put dsp in reset and take ASIC out of reset 916 + DEBUG("ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n"); 917 + ft1000_write_register (ft1000dev, DSP_RESET_BIT, FT1000_REG_RESET); 918 + 919 + // Setting MAGNEMITE ASIC to big endian mode 920 + ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); 921 + 922 + // Take DSP out of reset 923 + 924 + ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET); 925 + tempword |= DSP_ENCRYPTED; 926 + tempword &= ~DSP_UNENCRYPTED; 927 + ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 928 + tempword &= ~EFUSE_MEM_DISABLE; 929 + ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 930 + tempword &= ~DSP_RESET_BIT; 931 + ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET); 932 + 933 + 934 + // FLARION_DSP_ACTIVE; 935 + mdelay(10); 936 + DEBUG("ft1000_hw:ft1000_reset_card:Take DSP out of reset\n"); 937 + 938 + // Wait for 0xfefe indicating dsp ready before starting download 939 + for (i=0; i<50; i++) { 940 + //tempword = ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, FT1000_MAG_DPRAM_FEFE_INDX); 941 + ft1000_read_dpram32 (ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX, (PUCHAR)&templong, 4); 942 + if (tempword == 0xfefe) { 943 + break; 944 + } 945 + mdelay(20); 946 + } 947 + 948 + if (i==50) { 949 + DEBUG("ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n"); 950 + return FALSE; 951 + } 952 + 953 + 954 + #endif 955 + 956 + DEBUG("ft1000_hw:ft1000_reset_card: call dsp_reload\n"); 957 + dsp_reload(ft1000dev); 958 + 959 + DEBUG("dsp reload successful\n"); 960 + 961 + 962 + mdelay(10); 963 + 964 + // Initialize DSP heartbeat area to ho 965 + ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag, FT1000_MAG_HI_HO_INDX); 966 + ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (PCHAR)&tempword, FT1000_MAG_HI_HO_INDX); 967 + DEBUG("ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n", tempword); 968 + 969 + 970 + 971 + info->CardReady = 1; 972 + //ft1000_enable_interrupts(dev); 973 + /* Schedule heartbeat process to run every 2 seconds */ 974 + //poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 975 + //poll_timer[info->CardNumber].data = (u_long)dev; 976 + //add_timer(&poll_timer[info->CardNumber]); 977 + 978 + info->fCondResetPend = 0; 979 + return TRUE; 980 + 981 + } 982 + 983 + 984 + //mbelian 985 + #ifdef HAVE_NET_DEVICE_OPS 986 + static const struct net_device_ops ftnet_ops = 987 + { 988 + .ndo_open = &ft1000_open, 989 + .ndo_stop = &ft1000_close, 990 + .ndo_start_xmit = &ft1000_start_xmit, 991 + .ndo_get_stats = &ft1000_netdev_stats, 992 + }; 993 + #endif 994 + 995 + 996 + //--------------------------------------------------------------------------- 997 + // Function: init_ft1000_netdev 998 + // 999 + // Parameters: ft1000dev - device structure 1000 + // 1001 + // 1002 + // Returns: STATUS_SUCCESS - success 1003 + // STATUS_FAILURE - failure 1004 + // 1005 + // Description: This function initialize the network device 1006 + // 1007 + // Notes: 1008 + // 1009 + //--------------------------------------------------------------------------- 1010 + u16 init_ft1000_netdev(struct ft1000_device *ft1000dev) 1011 + { 1012 + struct net_device *netdev; 1013 + FT1000_INFO *pInfo = NULL; 1014 + PDPRAM_BLK pdpram_blk; 1015 + int i; 1016 + 1017 + gCardIndex=0; //mbelian 1018 + 1019 + DEBUG("Enter init_ft1000_netdev...\n"); 1020 + 1021 + 1022 + netdev = alloc_etherdev( sizeof(FT1000_INFO)); 1023 + if (!netdev ) 1024 + { 1025 + DEBUG("init_ft1000_netdev: can not allocate network device\n"); 1026 + return STATUS_FAILURE; 1027 + } 1028 + 1029 + //pInfo = (PFT1000_INFO)netdev->priv; 1030 + pInfo = (FT1000_INFO *) netdev_priv (netdev); 1031 + 1032 + //DEBUG("init_ft1000_netdev: gFt1000Info=%x, netdev=%x, ft1000dev=%x\n", gFt1000Info, netdev, ft1000dev); 1033 + 1034 + memset (pInfo, 0, sizeof(FT1000_INFO)); 1035 + 1036 + dev_alloc_name(netdev, netdev->name); 1037 + 1038 + //for the first inserted card, decide the card index beginning number, in case there are existing network interfaces 1039 + if ( gCardIndex == 0 ) 1040 + { 1041 + DEBUG("init_ft1000_netdev: network device name is %s\n", netdev->name); 1042 + 1043 + if ( strncmp(netdev->name,"eth", 3) == 0) { 1044 + //pInfo->CardNumber = atoi(&netdev->name[3]); 1045 + gCardIndex = atoi(&netdev->name[3]); 1046 + pInfo->CardNumber = gCardIndex; 1047 + DEBUG("card number = %d\n", pInfo->CardNumber); 1048 + } 1049 + else { 1050 + printk(KERN_ERR "ft1000: Invalid device name\n"); 1051 + kfree(netdev); 1052 + return STATUS_FAILURE; 1053 + } 1054 + } 1055 + else 1056 + { 1057 + //not the first inserted card, increase card number by 1 1058 + /*gCardIndex ++;*/ 1059 + pInfo->CardNumber = gCardIndex; 1060 + /*DEBUG("card number = %d\n", pInfo->CardNumber);*/ //mbelian 1061 + } 1062 + 1063 + memset(&pInfo->stats, 0, sizeof(struct net_device_stats) ); 1064 + 1065 + spin_lock_init(&pInfo->dpram_lock); 1066 + pInfo->pFt1000Dev = ft1000dev; 1067 + pInfo->DrvErrNum = 0; 1068 + pInfo->ASICResetNum = 0; 1069 + pInfo->registered = 1; 1070 + pInfo->ft1000_reset = ft1000_reset; 1071 + pInfo->mediastate = 0; 1072 + pInfo->fifo_cnt = 0; 1073 + pInfo->DeviceCreated = FALSE; 1074 + pInfo->DeviceMajor = 0; 1075 + pInfo->CurrentInterruptEnableMask = ISR_DEFAULT_MASK; 1076 + pInfo->InterruptsEnabled = FALSE; 1077 + pInfo->CardReady = 0; 1078 + pInfo->DSP_loading = 0; 1079 + pInfo->DSP_TIME[0] = 0; 1080 + pInfo->DSP_TIME[1] = 0; 1081 + pInfo->DSP_TIME[2] = 0; 1082 + pInfo->DSP_TIME[3] = 0; 1083 + pInfo->fAppMsgPend = 0; 1084 + pInfo->fCondResetPend = 0; 1085 + pInfo->usbboot = 0; 1086 + pInfo->dspalive = 0; 1087 + for (i=0;i<32 ;i++ ) 1088 + { 1089 + pInfo->tempbuf[i] = 0; 1090 + } 1091 + 1092 + INIT_LIST_HEAD(&pInfo->prov_list); 1093 + 1094 + //mbelian 1095 + #ifdef HAVE_NET_DEVICE_OPS 1096 + netdev->netdev_ops = &ftnet_ops; 1097 + #else 1098 + netdev->hard_start_xmit = &ft1000_start_xmit; 1099 + netdev->get_stats = &ft1000_netdev_stats; 1100 + netdev->open = &ft1000_open; 1101 + netdev->stop = &ft1000_close; 1102 + #endif 1103 + 1104 + //netif_stop_queue(netdev); //mbelian 1105 + 1106 + 1107 + ft1000dev->net = netdev; 1108 + 1109 + 1110 + 1111 + //init free_buff_lock, freercvpool, numofmsgbuf, pdpram_blk 1112 + //only init once per card 1113 + //Jim 1114 + DEBUG("Initialize free_buff_lock and freercvpool\n"); 1115 + spin_lock_init(&free_buff_lock); 1116 + 1117 + // initialize a list of buffers to be use for queuing up receive command data 1118 + INIT_LIST_HEAD (&freercvpool); 1119 + 1120 + // create list of free buffers 1121 + for (i=0; i<NUM_OF_FREE_BUFFERS; i++) { 1122 + // Get memory for DPRAM_DATA link list 1123 + pdpram_blk = kmalloc ( sizeof(DPRAM_BLK), GFP_KERNEL ); 1124 + // Get a block of memory to store command data 1125 + pdpram_blk->pbuffer = kmalloc ( MAX_CMD_SQSIZE, GFP_KERNEL ); 1126 + // link provisioning data 1127 + list_add_tail (&pdpram_blk->list, &freercvpool); 1128 + } 1129 + numofmsgbuf = NUM_OF_FREE_BUFFERS; 1130 + 1131 + 1132 + return STATUS_SUCCESS; 1133 + 1134 + } 1135 + 1136 + 1137 + 1138 + //--------------------------------------------------------------------------- 1139 + // Function: reg_ft1000_netdev 1140 + // 1141 + // Parameters: ft1000dev - device structure 1142 + // 1143 + // 1144 + // Returns: STATUS_SUCCESS - success 1145 + // STATUS_FAILURE - failure 1146 + // 1147 + // Description: This function register the network driver 1148 + // 1149 + // Notes: 1150 + // 1151 + //--------------------------------------------------------------------------- 1152 + u16 reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf) 1153 + { 1154 + struct net_device *netdev; 1155 + FT1000_INFO *pInfo; 1156 + int i, rc; 1157 + 1158 + netdev = ft1000dev->net; 1159 + pInfo = netdev_priv(ft1000dev->net); 1160 + DEBUG("Enter reg_ft1000_netdev...\n"); 1161 + 1162 + 1163 + ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID); 1164 + 1165 + usb_set_intfdata(intf, pInfo); 1166 + SET_NETDEV_DEV(netdev, &intf->dev); 1167 + 1168 + rc = register_netdev(netdev); 1169 + if (rc) 1170 + { 1171 + DEBUG("reg_ft1000_netdev: could not register network device\n"); 1172 + free_netdev(netdev); 1173 + return STATUS_FAILURE; 1174 + } 1175 + 1176 + 1177 + //Create character device, implemented by Jim 1178 + ft1000_CreateDevice(ft1000dev); 1179 + 1180 + //INIT_LIST_HEAD(&pInfo->prov_list); 1181 + 1182 + for (i=0; i<MAX_NUM_CARDS; i++) { 1183 + poll_timer[i].function = ft1000_hbchk; 1184 + } 1185 + 1186 + 1187 + //hard code MAC address for now 1188 + /** 1189 + netdev->dev_addr[0] = 0; 1190 + netdev->dev_addr[1] = 7; 1191 + netdev->dev_addr[2] = 0x35; 1192 + netdev->dev_addr[3] = 0x84; 1193 + netdev->dev_addr[4] = 0; 1194 + netdev->dev_addr[5] = 0x20 + pInfo->CardNumber; 1195 + **/ 1196 + 1197 + DEBUG ("reg_ft1000_netdev returned\n"); 1198 + 1199 + pInfo->CardReady = 1; 1200 + 1201 + 1202 + return STATUS_SUCCESS; 1203 + } 1204 + 1205 + int ft1000_reset(struct net_device *dev) 1206 + { 1207 + ft1000_reset_card(dev); 1208 + return 0; 1209 + } 1210 + 1211 + //--------------------------------------------------------------------------- 1212 + // Function: ft1000_usb_transmit_complete 1213 + // 1214 + // Parameters: urb - transmitted usb urb 1215 + // 1216 + // 1217 + // Returns: none 1218 + // 1219 + // Description: This is the callback function when a urb is transmitted 1220 + // 1221 + // Notes: 1222 + // 1223 + //--------------------------------------------------------------------------- 1224 + static void ft1000_usb_transmit_complete(struct urb *urb) 1225 + { 1226 + 1227 + struct ft1000_device *ft1000dev = urb->context; 1228 + 1229 + //DEBUG("ft1000_usb_transmit_complete entered\n"); 1230 + // Jim spin_lock(&ft1000dev->device_lock); 1231 + 1232 + if (urb->status) 1233 + printk("%s: TX status %d\n", ft1000dev->net->name, urb->status); 1234 + 1235 + netif_wake_queue(ft1000dev->net); 1236 + 1237 + //Jim spin_unlock(&ft1000dev->device_lock); 1238 + //DEBUG("Return from ft1000_usb_transmit_complete\n"); 1239 + } 1240 + 1241 + 1242 + /**************************************************************** 1243 + * ft1000_control 1244 + ****************************************************************/ 1245 + static int ft1000_read_fifo_reg(struct ft1000_device *ft1000dev,unsigned int pipe, 1246 + u8 request, 1247 + u8 requesttype, 1248 + u16 value, 1249 + u16 index, 1250 + void *data, 1251 + u16 size, 1252 + int timeout) 1253 + { 1254 + u16 ret; 1255 + 1256 + DECLARE_WAITQUEUE(wait, current); 1257 + struct urb *urb; 1258 + struct usb_ctrlrequest *dr; 1259 + int status; 1260 + 1261 + if (ft1000dev == NULL ) 1262 + { 1263 + DEBUG("NULL ft1000dev, failure\n"); 1264 + return STATUS_FAILURE; 1265 + } 1266 + else if ( ft1000dev->dev == NULL ) 1267 + { 1268 + DEBUG("NULL ft1000dev->dev, failure\n"); 1269 + return STATUS_FAILURE; 1270 + } 1271 + 1272 + spin_lock(&ft1000dev->device_lock); 1273 + 1274 + /*DECLARE_WAITQUEUE(wait, current); 1275 + struct urb *urb; 1276 + struct usb_ctrlrequest *dr; 1277 + int status;*/ 1278 + 1279 + if(in_interrupt()) 1280 + { 1281 + spin_unlock(&ft1000dev->device_lock); 1282 + return -EBUSY; 1283 + } 1284 + 1285 + urb = usb_alloc_urb(0, GFP_KERNEL); 1286 + dr = kmalloc(sizeof(struct usb_ctrlrequest), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); 1287 + 1288 + if(!urb || !dr) 1289 + { 1290 + if(urb) kfree(urb); 1291 + spin_unlock(&ft1000dev->device_lock); 1292 + return -ENOMEM; 1293 + } 1294 + 1295 + 1296 + 1297 + dr->bRequestType = requesttype; 1298 + dr->bRequest = request; 1299 + dr->wValue = value; 1300 + dr->wIndex = index; 1301 + dr->wLength = size; 1302 + 1303 + usb_fill_control_urb(urb, ft1000dev->dev, pipe, (char*)dr, (void*)data, size, (void *)ft1000_control_complete, (void*)ft1000dev); 1304 + 1305 + 1306 + init_waitqueue_head(&ft1000dev->control_wait); 1307 + 1308 + //current->state = TASK_INTERRUPTIBLE; //mbelian 1309 + set_current_state(TASK_INTERRUPTIBLE); 1310 + 1311 + add_wait_queue(&ft1000dev->control_wait, &wait); 1312 + 1313 + 1314 + 1315 + 1316 + status = usb_submit_urb(urb, GFP_KERNEL); 1317 + 1318 + if(status) 1319 + { 1320 + usb_free_urb(urb); 1321 + kfree(dr); 1322 + remove_wait_queue(&ft1000dev->control_wait, &wait); 1323 + spin_unlock(&ft1000dev->device_lock); 1324 + return status; 1325 + } 1326 + 1327 + if(urb->status == -EINPROGRESS) 1328 + { 1329 + while(timeout && urb->status == -EINPROGRESS) 1330 + { 1331 + status = timeout = schedule_timeout(timeout); 1332 + } 1333 + } 1334 + else 1335 + { 1336 + status = 1; 1337 + } 1338 + 1339 + remove_wait_queue(&ft1000dev->control_wait, &wait); 1340 + 1341 + if(!status) 1342 + { 1343 + usb_unlink_urb(urb); 1344 + printk("ft1000 timeout\n"); 1345 + status = -ETIMEDOUT; 1346 + } 1347 + else 1348 + { 1349 + status = urb->status; 1350 + 1351 + if(urb->status) 1352 + { 1353 + printk("ft1000 control message failed (urb addr: %x) with error number: %i\n", (int)urb, (int)status); 1354 + 1355 + usb_clear_halt(ft1000dev->dev, usb_rcvctrlpipe(ft1000dev->dev, 0)); 1356 + usb_clear_halt(ft1000dev->dev, usb_sndctrlpipe(ft1000dev->dev, 0)); 1357 + usb_unlink_urb(urb); 1358 + } 1359 + } 1360 + 1361 + 1362 + 1363 + usb_free_urb(urb); 1364 + kfree(dr); 1365 + spin_unlock(&ft1000dev->device_lock); 1366 + return ret; 1367 + 1368 + 1369 + } 1370 + 1371 + //--------------------------------------------------------------------------- 1372 + // Function: ft1000_read_fifo_len 1373 + // 1374 + // Parameters: ft1000dev - device structure 1375 + // 1376 + // 1377 + // Returns: none 1378 + // 1379 + // Description: read the fifo length register content 1380 + // 1381 + // Notes: 1382 + // 1383 + //--------------------------------------------------------------------------- 1384 + static inline u16 ft1000_read_fifo_len (struct net_device *dev) 1385 + { 1386 + u16 temp; 1387 + u16 ret; 1388 + 1389 + //FT1000_INFO *info = (PFT1000_INFO)dev->priv; 1390 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev); 1391 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 1392 + // DEBUG("ft1000_read_fifo_len: enter ft1000dev %x\n", ft1000dev); //aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct ft1000_device *??? 1393 + DEBUG("ft1000_read_fifo_len: enter ft1000dev %x\n", (unsigned int)ft1000dev); //aelias [+] reason: up 1394 + //ft1000_read_register(ft1000dev, &temp, FT1000_REG_MAG_UFSR); 1395 + 1396 + ret = STATUS_SUCCESS; 1397 + 1398 + ret = ft1000_read_fifo_reg(ft1000dev, 1399 + usb_rcvctrlpipe(ft1000dev->dev,0), 1400 + HARLEY_READ_REGISTER, 1401 + HARLEY_READ_OPERATION, 1402 + 0, 1403 + FT1000_REG_MAG_UFSR, 1404 + &temp, 1405 + 2, 1406 + LARGE_TIMEOUT); 1407 + 1408 + if (ret>0) 1409 + ret = STATUS_SUCCESS; 1410 + else 1411 + ret = STATUS_FAILURE; 1412 + 1413 + DEBUG("ft1000_read_fifo_len: returned %d\n", temp); 1414 + 1415 + return (temp- 16); 1416 + 1417 + } 1418 + 1419 + 1420 + //--------------------------------------------------------------------------- 1421 + // 1422 + // Function: ft1000_copy_down_pkt 1423 + // Descripton: This function will take an ethernet packet and convert it to 1424 + // a Flarion packet prior to sending it to the ASIC Downlink 1425 + // FIFO. 1426 + // Input: 1427 + // dev - device structure 1428 + // packet - address of ethernet packet 1429 + // len - length of IP packet 1430 + // Output: 1431 + // status - FAILURE 1432 + // SUCCESS 1433 + // 1434 + //--------------------------------------------------------------------------- 1435 + int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len) 1436 + { 1437 + FT1000_INFO *pInfo = netdev_priv(netdev); 1438 + struct ft1000_device *pFt1000Dev = pInfo->pFt1000Dev; 1439 + 1440 + 1441 + int i, count, ret; 1442 + USHORT *pTemp; 1443 + USHORT checksum; 1444 + u8 *t; 1445 + 1446 + if (!pInfo->CardReady) 1447 + { 1448 + 1449 + DEBUG("ft1000_copy_down_pkt::Card Not Ready\n"); 1450 + return STATUS_FAILURE; 1451 + 1452 + } 1453 + 1454 + 1455 + //DEBUG("ft1000_copy_down_pkt() entered, len = %d\n", len); 1456 + 1457 + #if 0 1458 + // Check if there is room on the FIFO 1459 + if ( len > ft1000_read_fifo_len (netdev) ) 1460 + { 1461 + udelay(10); 1462 + if ( len > ft1000_read_fifo_len (netdev) ) 1463 + { 1464 + udelay(20); 1465 + } 1466 + 1467 + if ( len > ft1000_read_fifo_len (netdev) ) 1468 + { 1469 + udelay(20); 1470 + } 1471 + 1472 + if ( len > ft1000_read_fifo_len (netdev) ) 1473 + { 1474 + udelay(20); 1475 + } 1476 + 1477 + if ( len > ft1000_read_fifo_len (netdev) ) 1478 + { 1479 + udelay(20); 1480 + } 1481 + 1482 + if ( len > ft1000_read_fifo_len (netdev) ) 1483 + { 1484 + udelay(20); 1485 + } 1486 + 1487 + if ( len > ft1000_read_fifo_len (netdev) ) 1488 + { 1489 + DEBUG("ft1000_hw:ft1000_copy_down_pkt:Transmit FIFO is fulli - pkt drop\n"); 1490 + pInfo->stats.tx_errors++; 1491 + return STATUS_SUCCESS; 1492 + } 1493 + } 1494 + #endif 1495 + 1496 + count = sizeof (PSEUDO_HDR) + len; 1497 + if(count > MAX_BUF_SIZE) 1498 + { 1499 + DEBUG("Error:ft1000_copy_down_pkt:Message Size Overflow!\n"); 1500 + DEBUG("size = %d\n", count); 1501 + return STATUS_FAILURE; 1502 + } 1503 + 1504 + if ( count % 4) 1505 + count = count + (4- (count %4) ); 1506 + 1507 + pTemp = (PUSHORT)&(pFt1000Dev->tx_buf[0]); 1508 + *pTemp ++ = ntohs(count); 1509 + *pTemp ++ = 0x1020; 1510 + *pTemp ++ = 0x2010; 1511 + *pTemp ++ = 0x9100; 1512 + *pTemp ++ = 0; 1513 + *pTemp ++ = 0; 1514 + *pTemp ++ = 0; 1515 + pTemp = (PUSHORT)&(pFt1000Dev->tx_buf[0]); 1516 + checksum = *pTemp ++; 1517 + for (i=1; i<7; i++) 1518 + { 1519 + checksum ^= *pTemp ++; 1520 + } 1521 + *pTemp++ = checksum; 1522 + memcpy (&(pFt1000Dev->tx_buf[sizeof(PSEUDO_HDR)]), packet, len); 1523 + 1524 + //usb_init_urb(pFt1000Dev->tx_urb); //mbelian 1525 + 1526 + netif_stop_queue(netdev); 1527 + 1528 + //DEBUG ("ft1000_copy_down_pkt: count = %d\n", count); 1529 + 1530 + usb_fill_bulk_urb(pFt1000Dev->tx_urb, 1531 + pFt1000Dev->dev, 1532 + usb_sndbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_out_endpointAddr), 1533 + pFt1000Dev->tx_buf, 1534 + count, 1535 + ft1000_usb_transmit_complete, 1536 + (void*)pFt1000Dev); 1537 + 1538 + t = (u8 *)pFt1000Dev->tx_urb->transfer_buffer; 1539 + //DEBUG("transfer_length=%d\n", pFt1000Dev->tx_urb->transfer_buffer_length); 1540 + /*for (i=0; i<count; i++ ) 1541 + { 1542 + DEBUG("%x ", *t++ ); 1543 + }*/ 1544 + 1545 + 1546 + ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC); 1547 + if(ret) 1548 + { 1549 + DEBUG("ft1000 failed tx_urb %d\n", ret); 1550 + 1551 + /* pInfo->stats.tx_errors++; 1552 + 1553 + netif_start_queue(netdev); */ //mbelian 1554 + return STATUS_FAILURE; 1555 + 1556 + } 1557 + else 1558 + { 1559 + //DEBUG("ft1000 sucess tx_urb %d\n", ret); 1560 + 1561 + pInfo->stats.tx_packets++; 1562 + pInfo->stats.tx_bytes += (len+14); 1563 + } 1564 + 1565 + //DEBUG("ft1000_copy_down_pkt() exit\n"); 1566 + 1567 + return STATUS_SUCCESS; 1568 + } 1569 + 1570 + //--------------------------------------------------------------------------- 1571 + // Function: ft1000_start_xmit 1572 + // 1573 + // Parameters: skb - socket buffer to be sent 1574 + // dev - network device 1575 + // 1576 + // 1577 + // Returns: none 1578 + // 1579 + // Description: transmit a ethernet packet 1580 + // 1581 + // Notes: 1582 + // 1583 + //--------------------------------------------------------------------------- 1584 + static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev) 1585 + { 1586 + FT1000_INFO *pInfo = netdev_priv(dev); 1587 + struct ft1000_device *pFt1000Dev= pInfo->pFt1000Dev; 1588 + u8 *pdata; 1589 + int maxlen, pipe; 1590 + 1591 + 1592 + //DEBUG(" ft1000_start_xmit() entered\n"); 1593 + 1594 + if ( skb == NULL ) 1595 + { 1596 + DEBUG ("ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n" ); 1597 + return STATUS_FAILURE; 1598 + } 1599 + 1600 + if ( pFt1000Dev->status & FT1000_STATUS_CLOSING) 1601 + { 1602 + DEBUG("network driver is closed, return\n"); 1603 + dev_kfree_skb(skb); 1604 + //usb_kill_urb(pFt1000Dev->tx_urb); //mbelian 1605 + return STATUS_SUCCESS; 1606 + } 1607 + 1608 + //DEBUG("ft1000_start_xmit 1:length of packet = %d\n", skb->len); 1609 + pipe = usb_sndbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_out_endpointAddr); 1610 + maxlen = usb_maxpacket(pFt1000Dev->dev, pipe, usb_pipeout(pipe)); 1611 + //DEBUG("ft1000_start_xmit 2: pipe=%d dev->maxpacket = %d\n", pipe, maxlen); 1612 + 1613 + pdata = (u8 *)skb->data; 1614 + /*for (i=0; i<skb->len; i++) 1615 + DEBUG("skb->data[%d]=%x ", i, *(skb->data+i)); 1616 + 1617 + DEBUG("\n");*/ 1618 + 1619 + 1620 + if (pInfo->mediastate == 0) 1621 + { 1622 + /* Drop packet is mediastate is down */ 1623 + DEBUG("ft1000_hw:ft1000_start_xmit:mediastate is down\n"); 1624 + dev_kfree_skb(skb); 1625 + return STATUS_SUCCESS; 1626 + } 1627 + 1628 + if ( (skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE) ) 1629 + { 1630 + /* Drop packet which has invalid size */ 1631 + DEBUG("ft1000_hw:ft1000_start_xmit:invalid ethernet length\n"); 1632 + dev_kfree_skb(skb); 1633 + return STATUS_SUCCESS; 1634 + } 1635 + //mbelian 1636 + if(ft1000_copy_down_pkt (dev, (pdata+ENET_HEADER_SIZE-2), skb->len - ENET_HEADER_SIZE + 2) == STATUS_FAILURE) 1637 + { 1638 + dev_kfree_skb(skb); 1639 + return STATUS_SUCCESS; 1640 + } 1641 + 1642 + dev_kfree_skb(skb); 1643 + //DEBUG(" ft1000_start_xmit() exit\n"); 1644 + 1645 + return 0; 1646 + } 1647 + 1648 + //--------------------------------------------------------------------------- 1649 + // 1650 + // Function: ft1000_copy_up_pkt 1651 + // Descripton: This function will take a packet from the FIFO up link and 1652 + // convert it into an ethernet packet and deliver it to the IP stack 1653 + // Input: 1654 + // urb - the receving usb urb 1655 + // 1656 + // Output: 1657 + // status - FAILURE 1658 + // SUCCESS 1659 + // 1660 + //--------------------------------------------------------------------------- 1661 + int ft1000_copy_up_pkt (struct urb *urb) 1662 + { 1663 + PFT1000_INFO info = urb->context; 1664 + struct ft1000_device *ft1000dev = info->pFt1000Dev; 1665 + struct net_device *net = ft1000dev->net; 1666 + 1667 + u16 tempword; 1668 + u16 len; 1669 + u16 lena; //mbelian 1670 + struct sk_buff *skb; 1671 + u16 i; 1672 + u8 *pbuffer=NULL; 1673 + u8 *ptemp=NULL; 1674 + u16 *chksum; 1675 + 1676 + 1677 + //DEBUG("ft1000_copy_up_pkt entered\n"); 1678 + 1679 + if ( ft1000dev->status & FT1000_STATUS_CLOSING) 1680 + { 1681 + DEBUG("network driver is closed, return\n"); 1682 + return STATUS_SUCCESS; 1683 + } 1684 + 1685 + // Read length 1686 + len = urb->transfer_buffer_length; 1687 + lena = urb->actual_length; //mbelian 1688 + //DEBUG("ft1000_copy_up_pkt: transfer_buffer_length=%d, actual_buffer_len=%d\n", 1689 + // urb->transfer_buffer_length, urb->actual_length); 1690 + 1691 + chksum = (PUSHORT)ft1000dev->rx_buf; 1692 + 1693 + tempword = *chksum++; 1694 + for (i=1; i<7; i++) 1695 + { 1696 + tempword ^= *chksum++; 1697 + } 1698 + 1699 + if (tempword != *chksum) 1700 + { 1701 + info->stats.rx_errors ++; 1702 + ft1000_submit_rx_urb(info); 1703 + return STATUS_FAILURE; 1704 + } 1705 + 1706 + 1707 + //DEBUG("ft1000_copy_up_pkt: checksum is correct %x\n", *chksum); 1708 + 1709 + skb = dev_alloc_skb(len+12+2); 1710 + 1711 + if (skb == NULL) 1712 + { 1713 + DEBUG("ft1000_copy_up_pkt: No Network buffers available\n"); 1714 + info->stats.rx_errors++; 1715 + ft1000_submit_rx_urb(info); 1716 + return STATUS_FAILURE; 1717 + } 1718 + 1719 + pbuffer = (u8 *)skb_put(skb, len+12); 1720 + 1721 + //subtract the number of bytes read already 1722 + ptemp = pbuffer; 1723 + 1724 + // fake MAC address 1725 + *pbuffer++ = net->dev_addr[0]; 1726 + *pbuffer++ = net->dev_addr[1]; 1727 + *pbuffer++ = net->dev_addr[2]; 1728 + *pbuffer++ = net->dev_addr[3]; 1729 + *pbuffer++ = net->dev_addr[4]; 1730 + *pbuffer++ = net->dev_addr[5]; 1731 + *pbuffer++ = 0x00; 1732 + *pbuffer++ = 0x07; 1733 + *pbuffer++ = 0x35; 1734 + *pbuffer++ = 0xff; 1735 + *pbuffer++ = 0xff; 1736 + *pbuffer++ = 0xfe; 1737 + 1738 + 1739 + 1740 + 1741 + memcpy(pbuffer, ft1000dev->rx_buf+sizeof(PSEUDO_HDR), len-sizeof(PSEUDO_HDR)); 1742 + 1743 + //DEBUG("ft1000_copy_up_pkt: Data passed to Protocol layer\n"); 1744 + /*for (i=0; i<len+12; i++) 1745 + { 1746 + DEBUG("ft1000_copy_up_pkt: Protocol Data: 0x%x\n ", *ptemp++); 1747 + }*/ 1748 + 1749 + skb->dev = net; 1750 + 1751 + skb->protocol = eth_type_trans(skb, net); 1752 + skb->ip_summed = CHECKSUM_UNNECESSARY; 1753 + netif_rx(skb); 1754 + 1755 + info->stats.rx_packets++; 1756 + // Add on 12 bytes for MAC address which was removed 1757 + info->stats.rx_bytes += (lena+12); //mbelian 1758 + 1759 + ft1000_submit_rx_urb(info); 1760 + //DEBUG("ft1000_copy_up_pkt exited\n"); 1761 + return SUCCESS; 1762 + } 1763 + 1764 + //--------------------------------------------------------------------------- 1765 + // 1766 + // Function: ft1000_submit_rx_urb 1767 + // Descripton: the receiving function of the network driver 1768 + // 1769 + // Input: 1770 + // info - a private structure contains the device information 1771 + // 1772 + // Output: 1773 + // status - FAILURE 1774 + // SUCCESS 1775 + // 1776 + //--------------------------------------------------------------------------- 1777 + int ft1000_submit_rx_urb(PFT1000_INFO info) 1778 + { 1779 + int result; 1780 + struct ft1000_device *pFt1000Dev = info->pFt1000Dev; 1781 + 1782 + //netif_carrier_on(pFt1000Dev->net); 1783 + 1784 + //DEBUG ("ft1000_submit_rx_urb entered: sizeof rx_urb is %d\n", sizeof(*pFt1000Dev->rx_urb)); 1785 + if ( pFt1000Dev->status & FT1000_STATUS_CLOSING) 1786 + { 1787 + DEBUG("network driver is closed, return\n"); 1788 + //usb_kill_urb(pFt1000Dev->rx_urb); //mbelian 1789 + return STATUS_SUCCESS; 1790 + } 1791 + //memset(pFt1000Dev->rx_urb, 0, sizeof(*pFt1000Dev->rx_urb)); 1792 + //usb_init_urb(pFt1000Dev->rx_urb);//mbelian 1793 + 1794 + //spin_lock_init(&pFt1000Dev->rx_urb->lock); 1795 + 1796 + usb_fill_bulk_urb(pFt1000Dev->rx_urb, 1797 + pFt1000Dev->dev, 1798 + usb_rcvbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_in_endpointAddr), 1799 + pFt1000Dev->rx_buf, 1800 + MAX_BUF_SIZE, 1801 + (usb_complete_t)ft1000_copy_up_pkt, 1802 + info); 1803 + 1804 + 1805 + if((result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC))) 1806 + { 1807 + printk("ft1000_submit_rx_urb: submitting rx_urb %d failed\n", result); 1808 + return STATUS_FAILURE; 1809 + } 1810 + 1811 + //DEBUG("ft1000_submit_rx_urb exit: result=%d\n", result); 1812 + 1813 + return STATUS_SUCCESS; 1814 + } 1815 + 1816 + //--------------------------------------------------------------------------- 1817 + // Function: ft1000_open 1818 + // 1819 + // Parameters: 1820 + // dev - network device 1821 + // 1822 + // 1823 + // Returns: none 1824 + // 1825 + // Description: open the network driver 1826 + // 1827 + // Notes: 1828 + // 1829 + //--------------------------------------------------------------------------- 1830 + static int ft1000_open (struct net_device *dev) 1831 + { 1832 + FT1000_INFO *pInfo = (FT1000_INFO *)netdev_priv(dev); 1833 + struct timeval tv; //mbelian 1834 + 1835 + DEBUG("ft1000_open is called for card %d\n", pInfo->CardNumber); 1836 + //DEBUG("ft1000_open: dev->addr=%x, dev->addr_len=%d\n", dev->addr, dev->addr_len); 1837 + 1838 + pInfo->stats.rx_bytes = 0; //mbelian 1839 + pInfo->stats.tx_bytes = 0; //mbelian 1840 + pInfo->stats.rx_packets = 0; //mbelian 1841 + pInfo->stats.tx_packets = 0; //mbelian 1842 + do_gettimeofday(&tv); 1843 + pInfo->ConTm = tv.tv_sec; 1844 + pInfo->ProgConStat = 0; //mbelian 1845 + 1846 + 1847 + netif_start_queue(dev); 1848 + 1849 + //netif_device_attach(dev); 1850 + 1851 + netif_carrier_on(dev); //mbelian 1852 + 1853 + ft1000_submit_rx_urb(pInfo); 1854 + return 0; 1855 + } 1856 + 1857 + //--------------------------------------------------------------------------- 1858 + // Function: ft1000_close 1859 + // 1860 + // Parameters: 1861 + // net - network device 1862 + // 1863 + // 1864 + // Returns: none 1865 + // 1866 + // Description: close the network driver 1867 + // 1868 + // Notes: 1869 + // 1870 + //--------------------------------------------------------------------------- 1871 + int ft1000_close(struct net_device *net) 1872 + { 1873 + FT1000_INFO *pInfo = (FT1000_INFO *) netdev_priv (net); 1874 + struct ft1000_device *ft1000dev = pInfo->pFt1000Dev; 1875 + 1876 + //DEBUG ("ft1000_close: netdev->refcnt=%d\n", net->refcnt); 1877 + 1878 + ft1000dev->status |= FT1000_STATUS_CLOSING; 1879 + 1880 + //DEBUG("ft1000_close: calling usb_kill_urb \n"); 1881 + //usb_kill_urb(ft1000dev->rx_urb); 1882 + //usb_kill_urb(ft1000dev->tx_urb); 1883 + 1884 + 1885 + DEBUG("ft1000_close: pInfo=%x, ft1000dev=%x\n", (int)pInfo, (int)ft1000dev); 1886 + netif_carrier_off(net);//mbelian 1887 + netif_stop_queue(net); 1888 + //DEBUG("ft1000_close: netif_stop_queue called\n"); 1889 + ft1000dev->status &= ~FT1000_STATUS_CLOSING; 1890 + 1891 + pInfo->ProgConStat = 0xff; //mbelian 1892 + 1893 + 1894 + return 0; 1895 + } 1896 + 1897 + static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev) 1898 + { 1899 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev); 1900 + //struct ft1000_device *ft1000dev = info->pFt1000Dev; 1901 + 1902 + //return &(ft1000dev->stats);//mbelian 1903 + return &(info->stats); //mbelian 1904 + } 1905 + 1906 + 1907 + /********************************************************************************* 1908 + Jim 1909 + */ 1910 + 1911 + 1912 + //--------------------------------------------------------------------------- 1913 + // 1914 + // Function: ft1000_chkcard 1915 + // Descripton: This function will check if the device is presently available on 1916 + // the system. 1917 + // Input: 1918 + // dev - device structure 1919 + // Output: 1920 + // status - FALSE (device is not present) 1921 + // TRUE (device is present) 1922 + // 1923 + //--------------------------------------------------------------------------- 1924 + static int ft1000_chkcard (struct ft1000_device *dev) { 1925 + u16 tempword; 1926 + u16 status; 1927 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev->net); 1928 + 1929 + if (info->fCondResetPend) 1930 + { 1931 + DEBUG("ft1000_hw:ft1000_chkcard:Card is being reset, return FALSE\n"); 1932 + return TRUE; 1933 + } 1934 + 1935 + // Mask register is used to check for device presence since it is never 1936 + // set to zero. 1937 + status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK); 1938 + //DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_SUP_IMASK = %x\n", tempword); 1939 + if (tempword == 0) { 1940 + DEBUG("ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n"); 1941 + return FALSE; 1942 + } 1943 + 1944 + // The system will return the value of 0xffff for the version register 1945 + // if the device is not present. 1946 + status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID); 1947 + //DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_ASIC_ID = %x\n", tempword); 1948 + //pxu if (tempword == 0xffff) { 1949 + if (tempword != 0x1b01 ){ 1950 + dev->status |= FT1000_STATUS_CLOSING; //mbelian 1951 + DEBUG("ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n"); 1952 + return FALSE; 1953 + } 1954 + return TRUE; 1955 + } 1956 + 1957 + //--------------------------------------------------------------------------- 1958 + // 1959 + // Function: ft1000_hbchk 1960 + // Descripton: This function will perform the heart beat check of the DSP as 1961 + // well as the ASIC. 1962 + // Input: 1963 + // dev - device structure 1964 + // Output: 1965 + // none 1966 + // 1967 + //--------------------------------------------------------------------------- 1968 + static void ft1000_hbchk(u_long data) 1969 + { 1970 + struct ft1000_device *dev = (struct ft1000_device *)data; 1971 + 1972 + FT1000_INFO *info; 1973 + USHORT tempword; 1974 + u16 status; 1975 + info = (FT1000_INFO *) netdev_priv (dev->net); 1976 + 1977 + DEBUG("ft1000_hbchk called for CardNumber = %d CardReady = %d\n", info->CardNumber, info->CardReady); 1978 + 1979 + if (info->fCondResetPend == 1) { 1980 + // Reset ASIC and DSP 1981 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); 1982 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); 1983 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); 1984 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); 1985 + 1986 + info->DrvErrNum = DSP_CONDRESET_INFO; 1987 + DEBUG("ft1000_hw:DSP conditional reset requested\n"); 1988 + ft1000_reset_card(dev->net); 1989 + info->fCondResetPend = 0; 1990 + /* Schedule this module to run every 2 seconds */ 1991 + 1992 + poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 1993 + poll_timer[info->CardNumber].data = (u_long)dev; 1994 + add_timer(&poll_timer[info->CardNumber]); 1995 + 1996 + 1997 + 1998 + return; 1999 + } 2000 + 2001 + if (info->CardReady == 1) { 2002 + // Perform dsp heartbeat check 2003 + status = ntohs(ft1000_read_dpram16(dev, FT1000_MAG_HI_HO, (PUCHAR)&tempword, FT1000_MAG_HI_HO_INDX)); 2004 + DEBUG("ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n", tempword); 2005 + // Let's perform another check if ho is not detected 2006 + if (tempword != ho) { 2007 + status = ntohs(ft1000_read_dpram16(dev, FT1000_MAG_HI_HO, (PUCHAR)&tempword,FT1000_MAG_HI_HO_INDX)); 2008 + } 2009 + if (tempword != ho) { 2010 + printk(KERN_INFO "ft1000: heartbeat failed - no ho detected\n"); 2011 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); 2012 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); 2013 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); 2014 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); 2015 + info->DrvErrNum = DSP_HB_INFO; 2016 + if (ft1000_reset_card(dev->net) == 0) { 2017 + printk(KERN_INFO "ft1000: Hardware Failure Detected - PC Card disabled\n"); 2018 + info->ProgConStat = 0xff; 2019 + return; 2020 + } 2021 + /* Schedule this module to run every 2 seconds */ 2022 + poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 2023 + poll_timer[info->CardNumber].data = (u_long)dev; 2024 + add_timer(&poll_timer[info->CardNumber]); 2025 + return; 2026 + } 2027 + 2028 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2029 + // Let's check doorbell again if fail 2030 + if (tempword & FT1000_DB_HB) { 2031 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2032 + } 2033 + if (tempword & FT1000_DB_HB) { 2034 + printk(KERN_INFO "ft1000: heartbeat doorbell not clear by firmware\n"); 2035 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); 2036 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); 2037 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); 2038 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); 2039 + info->DrvErrNum = DSP_HB_INFO; 2040 + if (ft1000_reset_card(dev->net) == 0) { 2041 + printk(KERN_INFO "ft1000: Hardware Failure Detected - PC Card disabled\n"); 2042 + info->ProgConStat = 0xff; 2043 + return; 2044 + } 2045 + /* Schedule this module to run every 2 seconds */ 2046 + poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 2047 + poll_timer[info->CardNumber].data = (u_long)dev; 2048 + add_timer(&poll_timer[info->CardNumber]); 2049 + return; 2050 + } 2051 + 2052 + // Set dedicated area to hi and ring appropriate doorbell according 2053 + // to hi/ho heartbeat protocol 2054 + ft1000_write_dpram16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX); 2055 + 2056 + status = ntohs(ft1000_read_dpram16(dev, FT1000_MAG_HI_HO, (PUCHAR)&tempword, FT1000_MAG_HI_HO_INDX)); 2057 + // Let's write hi again if fail 2058 + if (tempword != hi) { 2059 + ft1000_write_dpram16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX); 2060 + status = ntohs(ft1000_read_dpram16(dev, FT1000_MAG_HI_HO, (PUCHAR)&tempword, FT1000_MAG_HI_HO_INDX)); 2061 + 2062 + } 2063 + if (tempword != hi) { 2064 + printk(KERN_INFO "ft1000: heartbeat failed - cannot write hi into DPRAM\n"); 2065 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); 2066 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); 2067 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); 2068 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); 2069 + 2070 + info->DrvErrNum = DSP_HB_INFO; 2071 + if (ft1000_reset_card(dev->net) == 0) { 2072 + printk(KERN_INFO "ft1000: Hardware Failure Detected - PC Card disabled\n"); 2073 + info->ProgConStat = 0xff; 2074 + return; 2075 + } 2076 + /* Schedule this module to run every 2 seconds */ 2077 + poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 2078 + poll_timer[info->CardNumber].data = (u_long)dev; 2079 + add_timer(&poll_timer[info->CardNumber]); 2080 + return; 2081 + } 2082 + ft1000_write_register(dev, FT1000_DB_HB, FT1000_REG_DOORBELL); 2083 + 2084 + } 2085 + 2086 + /* Schedule this module to run every 2 seconds */ 2087 + poll_timer[info->CardNumber].expires = jiffies + (2*HZ); 2088 + poll_timer[info->CardNumber].data = (u_long)dev; 2089 + add_timer(&poll_timer[info->CardNumber]); 2090 + } 2091 + 2092 + //--------------------------------------------------------------------------- 2093 + // 2094 + // Function: ft1000_receive_cmd 2095 + // Descripton: This function will read a message from the dpram area. 2096 + // Input: 2097 + // dev - network device structure 2098 + // pbuffer - caller supply address to buffer 2099 + // pnxtph - pointer to next pseudo header 2100 + // Output: 2101 + // Status = 0 (unsuccessful) 2102 + // = 1 (successful) 2103 + // 2104 + //--------------------------------------------------------------------------- 2105 + BOOLEAN ft1000_receive_cmd (struct ft1000_device *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { 2106 + u16 size, ret; 2107 + u16 *ppseudohdr; 2108 + int i; 2109 + u16 tempword; 2110 + 2111 + ret = ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (PUCHAR)&size, FT1000_MAG_PH_LEN_INDX); 2112 + size = ntohs(size) + PSEUDOSZ; 2113 + if (size > maxsz) { 2114 + DEBUG("FT1000:ft1000_receive_cmd:Invalid command length = %d\n", size); 2115 + return FALSE; 2116 + } 2117 + else { 2118 + ppseudohdr = (u16 *)pbuffer; 2119 + //spin_lock_irqsave (&info->dpram_lock, flags); 2120 + ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE, FT1000_REG_DPRAM_ADDR); 2121 + ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH); 2122 + //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer); 2123 + pbuffer++; 2124 + ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE+1, FT1000_REG_DPRAM_ADDR); 2125 + for (i=0; i<=(size>>2); i++) { 2126 + ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL); 2127 + pbuffer++; 2128 + ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH); 2129 + pbuffer++; 2130 + } 2131 + //copy odd aligned word 2132 + ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL); 2133 + //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer); 2134 + pbuffer++; 2135 + ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH); 2136 + //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer); 2137 + pbuffer++; 2138 + if (size & 0x0001) { 2139 + //copy odd byte from fifo 2140 + ret = ft1000_read_register(dev, &tempword, FT1000_REG_DPRAM_DATA); 2141 + *pbuffer = ntohs(tempword); 2142 + } 2143 + //spin_unlock_irqrestore(&info->dpram_lock, flags); 2144 + 2145 + // Check if pseudo header checksum is good 2146 + // Calculate pseudo header checksum 2147 + tempword = *ppseudohdr++; 2148 + for (i=1; i<7; i++) { 2149 + tempword ^= *ppseudohdr++; 2150 + } 2151 + if ( (tempword != *ppseudohdr) ) { 2152 + return FALSE; 2153 + } 2154 + 2155 + 2156 + #if 0 2157 + DEBUG("ft1000_receive_cmd:pbuffer\n"); 2158 + for(i = 0; i < size; i+=5) 2159 + { 2160 + if( (i + 5) < size ) 2161 + DEBUG("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", tempbuffer[i], tempbuffer[i+1], tempbuffer[i+2], tempbuffer[i+3], tempbuffer[i+4]); 2162 + else 2163 + { 2164 + for (j = i; j < size; j++) 2165 + DEBUG("0x%x ", tempbuffer[j]); 2166 + DEBUG("\n"); 2167 + break; 2168 + } 2169 + } 2170 + 2171 + #endif 2172 + 2173 + return TRUE; 2174 + } 2175 + } 2176 + 2177 + 2178 + int ft1000_dsp_prov(void *arg) 2179 + { 2180 + struct ft1000_device *dev = (struct ft1000_device *)arg; 2181 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev->net); 2182 + u16 tempword; 2183 + u16 len; 2184 + u16 i=0; 2185 + PPROV_RECORD ptr; 2186 + PPSEUDO_HDR ppseudo_hdr; 2187 + PUSHORT pmsg; 2188 + u16 status; 2189 + USHORT TempShortBuf [256]; 2190 + 2191 + DEBUG("*** DspProv Entered\n"); 2192 + 2193 + while ( list_empty(&info->prov_list) == 0 2194 + /*&& !kthread_should_stop() */) 2195 + { 2196 + DEBUG("DSP Provisioning List Entry\n"); 2197 + 2198 + // Check if doorbell is available 2199 + DEBUG("check if doorbell is cleared\n"); 2200 + status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL); 2201 + if (status) 2202 + { 2203 + DEBUG("ft1000_dsp_prov::ft1000_read_register error\n"); 2204 + break; 2205 + } 2206 + 2207 + while (tempword & FT1000_DB_DPRAM_TX) { 2208 + mdelay(10); 2209 + i++; 2210 + if (i==10) { 2211 + DEBUG("FT1000:ft1000_dsp_prov:message drop\n"); 2212 + return STATUS_FAILURE; 2213 + } 2214 + ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2215 + } 2216 + 2217 + if ( !(tempword & FT1000_DB_DPRAM_TX) ) { 2218 + DEBUG("*** Provision Data Sent to DSP\n"); 2219 + 2220 + // Send provisioning data 2221 + ptr = list_entry(info->prov_list.next, PROV_RECORD, list); 2222 + len = *(u16 *)ptr->pprov_data; 2223 + len = htons(len); 2224 + len += PSEUDOSZ; 2225 + //len = htons(len); 2226 + 2227 + pmsg = (PUSHORT)ptr->pprov_data; 2228 + ppseudo_hdr = (PPSEUDO_HDR)pmsg; 2229 + // Insert slow queue sequence number 2230 + ppseudo_hdr->seq_num = info->squeseqnum++; 2231 + ppseudo_hdr->portsrc = 0; 2232 + // Calculate new checksum 2233 + ppseudo_hdr->checksum = *pmsg++; 2234 + //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum); 2235 + for (i=1; i<7; i++) { 2236 + ppseudo_hdr->checksum ^= *pmsg++; 2237 + //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum); 2238 + } 2239 + 2240 + TempShortBuf[0] = 0; 2241 + TempShortBuf[1] = htons (len); 2242 + memcpy(&TempShortBuf[2], ppseudo_hdr, len); 2243 + 2244 + status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&TempShortBuf[0], (unsigned short)(len+2)); 2245 + status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL); 2246 + 2247 + list_del(&ptr->list); 2248 + kfree(ptr->pprov_data); 2249 + kfree(ptr); 2250 + } 2251 + msleep(10); 2252 + } 2253 + 2254 + DEBUG("DSP Provisioning List Entry finished\n"); 2255 + 2256 + msleep(100); 2257 + 2258 + info->fProvComplete = 1; 2259 + info->CardReady = 1; 2260 + info->DSP_loading= 0; 2261 + return STATUS_SUCCESS; 2262 + 2263 + } 2264 + 2265 + 2266 + int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { 2267 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev->net); 2268 + u16 msgtype; 2269 + u16 tempword; 2270 + PMEDIAMSG pmediamsg; 2271 + PDSPINITMSG pdspinitmsg; 2272 + PDRVMSG pdrvmsg; 2273 + u16 i; 2274 + PPSEUDO_HDR ppseudo_hdr; 2275 + PUSHORT pmsg; 2276 + u16 status; 2277 + //struct timeval tv; //mbelian 2278 + union { 2279 + u8 byte[2]; 2280 + u16 wrd; 2281 + } convert; 2282 + 2283 + 2284 + char cmdbuffer[1600]; 2285 + 2286 + status = ft1000_read_dpram32(dev, 0x200, (PUCHAR)&cmdbuffer[0], size); 2287 + 2288 + 2289 + //if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) 2290 + { 2291 + 2292 + #ifdef JDEBUG 2293 + DEBUG("ft1000_proc_drvmsg:cmdbuffer\n"); 2294 + for(i = 0; i < size; i+=5) 2295 + { 2296 + if( (i + 5) < size ) 2297 + DEBUG("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", cmdbuffer[i], cmdbuffer[i+1], cmdbuffer[i+2], cmdbuffer[i+3], cmdbuffer[i+4]); 2298 + else 2299 + { 2300 + for (j = i; j < size; j++) 2301 + DEBUG("0x%x ", cmdbuffer[j]); 2302 + DEBUG("\n"); 2303 + break; 2304 + } 2305 + } 2306 + #endif 2307 + pdrvmsg = (PDRVMSG)&cmdbuffer[2]; 2308 + msgtype = ntohs(pdrvmsg->type); 2309 + DEBUG("ft1000_proc_drvmsg:Command message type = 0x%x\n", msgtype); 2310 + switch (msgtype) { 2311 + case MEDIA_STATE: { 2312 + DEBUG("ft1000_proc_drvmsg:Command message type = MEDIA_STATE"); 2313 + 2314 + pmediamsg = (PMEDIAMSG)&cmdbuffer[0]; 2315 + if (info->ProgConStat != 0xFF) { 2316 + if (pmediamsg->state) { 2317 + DEBUG("Media is up\n"); 2318 + if (info->mediastate == 0) { 2319 + if ( info->NetDevRegDone ) 2320 + { 2321 + //netif_carrier_on(dev->net);//mbelian 2322 + netif_wake_queue(dev->net); 2323 + } 2324 + info->mediastate = 1; 2325 + /*do_gettimeofday(&tv); 2326 + info->ConTm = tv.tv_sec;*/ //mbelian 2327 + } 2328 + } 2329 + else { 2330 + DEBUG("Media is down\n"); 2331 + if (info->mediastate == 1) { 2332 + info->mediastate = 0; 2333 + if ( info->NetDevRegDone ) 2334 + { 2335 + //netif_carrier_off(dev->net); mbelian 2336 + //netif_stop_queue(dev->net); 2337 + } 2338 + info->ConTm = 0; 2339 + } 2340 + } 2341 + } 2342 + else { 2343 + DEBUG("Media is down\n"); 2344 + if (info->mediastate == 1) { 2345 + info->mediastate = 0; 2346 + if ( info->NetDevRegDone) 2347 + { 2348 + //netif_carrier_off(dev->net); //mbelian 2349 + //netif_stop_queue(dev->net); 2350 + } 2351 + info->ConTm = 0; 2352 + } 2353 + } 2354 + break; 2355 + } 2356 + case DSP_INIT_MSG: { 2357 + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_INIT_MSG"); 2358 + 2359 + pdspinitmsg = (PDSPINITMSG)&cmdbuffer[2]; 2360 + memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ); 2361 + DEBUG("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n", info->DspVer[0], info->DspVer[1], info->DspVer[2], info->DspVer[3]); 2362 + memcpy(info->HwSerNum, pdspinitmsg->HwSerNum, HWSERNUMSZ); 2363 + memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ); 2364 + memcpy(info->eui64, pdspinitmsg->eui64, EUISZ); 2365 + DEBUG("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n", info->eui64[0],info->eui64[1], info->eui64[2], info->eui64[3], info->eui64[4], info->eui64[5],info->eui64[6], info->eui64[7]); 2366 + dev->net->dev_addr[0] = info->eui64[0]; 2367 + dev->net->dev_addr[1] = info->eui64[1]; 2368 + dev->net->dev_addr[2] = info->eui64[2]; 2369 + dev->net->dev_addr[3] = info->eui64[5]; 2370 + dev->net->dev_addr[4] = info->eui64[6]; 2371 + dev->net->dev_addr[5] = info->eui64[7]; 2372 + 2373 + if (ntohs(pdspinitmsg->length) == (sizeof(DSPINITMSG) - 20) ) { 2374 + memcpy(info->ProductMode, pdspinitmsg->ProductMode, MODESZ); 2375 + memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, CALVERSZ); 2376 + memcpy(info->RfCalDate, pdspinitmsg->RfCalDate, CALDATESZ); 2377 + DEBUG("RFCalVer = 0x%2x 0x%2x\n", info->RfCalVer[0], info->RfCalVer[1]); 2378 + } 2379 + break; 2380 + } 2381 + case DSP_PROVISION: { 2382 + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_PROVISION\n"); 2383 + 2384 + // kick off dspprov routine to start provisioning 2385 + // Send provisioning data to DSP 2386 + if (list_empty(&info->prov_list) == 0) 2387 + { 2388 + info->fProvComplete = 0; 2389 + status = ft1000_dsp_prov(dev); 2390 + if (status != STATUS_SUCCESS) 2391 + return status; 2392 + } 2393 + else { 2394 + info->fProvComplete = 1; 2395 + status = ft1000_write_register (dev, FT1000_DB_HB, FT1000_REG_DOORBELL); 2396 + DEBUG("FT1000:drivermsg:No more DSP provisioning data in dsp image\n"); 2397 + } 2398 + DEBUG("ft1000_proc_drvmsg:DSP PROVISION is done\n"); 2399 + break; 2400 + } 2401 + case DSP_STORE_INFO: { 2402 + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_STORE_INFO"); 2403 + 2404 + DEBUG("FT1000:drivermsg:Got DSP_STORE_INFO\n"); 2405 + tempword = ntohs(pdrvmsg->length); 2406 + info->DSPInfoBlklen = tempword; 2407 + if (tempword < (MAX_DSP_SESS_REC-4) ) { 2408 + pmsg = (PUSHORT)&pdrvmsg->data[0]; 2409 + for (i=0; i<((tempword+1)/2); i++) { 2410 + DEBUG("FT1000:drivermsg:dsp info data = 0x%x\n", *pmsg); 2411 + info->DSPInfoBlk[i+10] = *pmsg++; 2412 + } 2413 + } 2414 + else { 2415 + info->DSPInfoBlklen = 0; 2416 + } 2417 + break; 2418 + } 2419 + case DSP_GET_INFO: { 2420 + DEBUG("FT1000:drivermsg:Got DSP_GET_INFO\n"); 2421 + // copy dsp info block to dsp 2422 + info->DrvMsgPend = 1; 2423 + // allow any outstanding ioctl to finish 2424 + mdelay(10); 2425 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2426 + if (tempword & FT1000_DB_DPRAM_TX) { 2427 + mdelay(10); 2428 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2429 + if (tempword & FT1000_DB_DPRAM_TX) { 2430 + mdelay(10); 2431 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2432 + if (tempword & FT1000_DB_DPRAM_TX) { 2433 + break; 2434 + } 2435 + } 2436 + } 2437 + 2438 + // Put message into Slow Queue 2439 + // Form Pseudo header 2440 + pmsg = (PUSHORT)info->DSPInfoBlk; 2441 + *pmsg++ = 0; 2442 + *pmsg++ = htons(info->DSPInfoBlklen+20+info->DSPInfoBlklen); 2443 + ppseudo_hdr = (PPSEUDO_HDR)(PUSHORT)&info->DSPInfoBlk[2]; 2444 + ppseudo_hdr->length = htons(info->DSPInfoBlklen+4+info->DSPInfoBlklen); 2445 + ppseudo_hdr->source = 0x10; 2446 + ppseudo_hdr->destination = 0x20; 2447 + ppseudo_hdr->portdest = 0; 2448 + ppseudo_hdr->portsrc = 0; 2449 + ppseudo_hdr->sh_str_id = 0; 2450 + ppseudo_hdr->control = 0; 2451 + ppseudo_hdr->rsvd1 = 0; 2452 + ppseudo_hdr->rsvd2 = 0; 2453 + ppseudo_hdr->qos_class = 0; 2454 + // Insert slow queue sequence number 2455 + ppseudo_hdr->seq_num = info->squeseqnum++; 2456 + // Insert application id 2457 + ppseudo_hdr->portsrc = 0; 2458 + // Calculate new checksum 2459 + ppseudo_hdr->checksum = *pmsg++; 2460 + for (i=1; i<7; i++) { 2461 + ppseudo_hdr->checksum ^= *pmsg++; 2462 + } 2463 + info->DSPInfoBlk[10] = 0x7200; 2464 + info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen); 2465 + status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&info->DSPInfoBlk[0], (unsigned short)(info->DSPInfoBlklen+22)); 2466 + status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL); 2467 + info->DrvMsgPend = 0; 2468 + 2469 + break; 2470 + } 2471 + 2472 + case GET_DRV_ERR_RPT_MSG: { 2473 + DEBUG("FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n"); 2474 + // copy driver error message to dsp 2475 + info->DrvMsgPend = 1; 2476 + // allow any outstanding ioctl to finish 2477 + mdelay(10); 2478 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2479 + if (tempword & FT1000_DB_DPRAM_TX) { 2480 + mdelay(10); 2481 + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); 2482 + if (tempword & FT1000_DB_DPRAM_TX) { 2483 + mdelay(10); 2484 + } 2485 + } 2486 + 2487 + if ( (tempword & FT1000_DB_DPRAM_TX) == 0) { 2488 + // Put message into Slow Queue 2489 + // Form Pseudo header 2490 + pmsg = (PUSHORT)&tempbuffer[0]; 2491 + ppseudo_hdr = (PPSEUDO_HDR)pmsg; 2492 + ppseudo_hdr->length = htons(0x0012); 2493 + ppseudo_hdr->source = 0x10; 2494 + ppseudo_hdr->destination = 0x20; 2495 + ppseudo_hdr->portdest = 0; 2496 + ppseudo_hdr->portsrc = 0; 2497 + ppseudo_hdr->sh_str_id = 0; 2498 + ppseudo_hdr->control = 0; 2499 + ppseudo_hdr->rsvd1 = 0; 2500 + ppseudo_hdr->rsvd2 = 0; 2501 + ppseudo_hdr->qos_class = 0; 2502 + // Insert slow queue sequence number 2503 + ppseudo_hdr->seq_num = info->squeseqnum++; 2504 + // Insert application id 2505 + ppseudo_hdr->portsrc = 0; 2506 + // Calculate new checksum 2507 + ppseudo_hdr->checksum = *pmsg++; 2508 + for (i=1; i<7; i++) { 2509 + ppseudo_hdr->checksum ^= *pmsg++; 2510 + } 2511 + pmsg = (PUSHORT)&tempbuffer[16]; 2512 + *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); 2513 + *pmsg++ = htons(0x000e); 2514 + *pmsg++ = htons(info->DSP_TIME[0]); 2515 + *pmsg++ = htons(info->DSP_TIME[1]); 2516 + *pmsg++ = htons(info->DSP_TIME[2]); 2517 + *pmsg++ = htons(info->DSP_TIME[3]); 2518 + convert.byte[0] = info->DspVer[0]; 2519 + convert.byte[1] = info->DspVer[1]; 2520 + *pmsg++ = convert.wrd; 2521 + convert.byte[0] = info->DspVer[2]; 2522 + convert.byte[1] = info->DspVer[3]; 2523 + *pmsg++ = convert.wrd; 2524 + *pmsg++ = htons(info->DrvErrNum); 2525 + 2526 + CardSendCommand (dev, (unsigned char*)&tempbuffer[0], (USHORT)(0x0012 + PSEUDOSZ)); 2527 + info->DrvErrNum = 0; 2528 + } 2529 + info->DrvMsgPend = 0; 2530 + 2531 + break; 2532 + } 2533 + 2534 + default: 2535 + break; 2536 + } 2537 + 2538 + } 2539 + 2540 + DEBUG("return from ft1000_proc_drvmsg\n"); 2541 + return STATUS_SUCCESS; 2542 + } 2543 + 2544 + 2545 + 2546 + int ft1000_poll(void* dev_id) { 2547 + 2548 + //FT1000_INFO *info = (PFT1000_INFO)((struct net_device *)dev_id)->priv; 2549 + //struct ft1000_device *dev = (struct ft1000_device *)info->pFt1000Dev; 2550 + struct ft1000_device *dev = (struct ft1000_device *)dev_id; 2551 + FT1000_INFO *info = (FT1000_INFO *) netdev_priv (dev->net); 2552 + 2553 + u16 tempword; 2554 + u16 status; 2555 + u16 size; 2556 + int i; 2557 + USHORT data; 2558 + USHORT modulo; 2559 + USHORT portid; 2560 + u16 nxtph; 2561 + PDPRAM_BLK pdpram_blk; 2562 + PPSEUDO_HDR ppseudo_hdr; 2563 + unsigned long flags; 2564 + 2565 + //DEBUG("Enter ft1000_poll...\n"); 2566 + if (ft1000_chkcard(dev) == FALSE) { 2567 + DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); 2568 + return STATUS_FAILURE; 2569 + } 2570 + 2571 + status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL); 2572 + // DEBUG("ft1000_poll: read FT1000_REG_DOORBELL message 0x%x\n", tempword); 2573 + 2574 + //while ( (tempword) && (!status) ) { 2575 + if ( !status ) 2576 + { 2577 + 2578 + if (tempword & FT1000_DB_DPRAM_RX) { 2579 + //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX\n"); 2580 + 2581 + status = ft1000_read_dpram16(dev, 0x200, (PUCHAR)&data, 0); 2582 + //DEBUG("ft1000_poll:FT1000_DB_DPRAM_RX:ft1000_read_dpram16:size = 0x%x\n", data); 2583 + size = ntohs(data) + 16 + 2; //wai 2584 + if (size % 4) { 2585 + modulo = 4 - (size % 4); 2586 + size = size + modulo; 2587 + } 2588 + status = ft1000_read_dpram16(dev, 0x201, (PUCHAR)&portid, 1); 2589 + portid &= 0xff; 2590 + //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid 0x%x\n", portid); 2591 + 2592 + if (size < MAX_CMD_SQSIZE) { 2593 + switch (portid) 2594 + { 2595 + case DRIVERID: 2596 + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n"); 2597 + 2598 + status = ft1000_proc_drvmsg (dev, size); 2599 + if (status != STATUS_SUCCESS ) 2600 + return status; 2601 + break; 2602 + case DSPBCMSGID: 2603 + // This is a dsp broadcast message 2604 + // Check which application has registered for dsp broadcast messages 2605 + //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DSPBCMSGID\n"); 2606 + 2607 + for (i=0; i<MAX_NUM_APP; i++) { 2608 + if ( (info->app_info[i].DspBCMsgFlag) && (info->app_info[i].fileobject) && 2609 + (info->app_info[i].NumOfMsg < MAX_MSG_LIMIT) ) 2610 + { 2611 + //DEBUG("Dsp broadcast message detected for app id %d\n", i); 2612 + nxtph = FT1000_DPRAM_RX_BASE + 2; 2613 + pdpram_blk = ft1000_get_buffer (&freercvpool); 2614 + if (pdpram_blk != NULL) { 2615 + if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE, &nxtph) ) { 2616 + ppseudo_hdr = (PPSEUDO_HDR)pdpram_blk->pbuffer; 2617 + // Put message into the appropriate application block 2618 + info->app_info[i].nRxMsg++; 2619 + spin_lock_irqsave(&free_buff_lock, flags); 2620 + list_add_tail(&pdpram_blk->list, &info->app_info[i].app_sqlist); 2621 + info->app_info[i].NumOfMsg++; 2622 + spin_unlock_irqrestore(&free_buff_lock, flags); 2623 + wake_up_interruptible(&info->app_info[i].wait_dpram_msg); 2624 + } 2625 + else { 2626 + info->app_info[i].nRxMsgMiss++; 2627 + // Put memory back to free pool 2628 + ft1000_free_buffer(pdpram_blk, &freercvpool); 2629 + DEBUG("pdpram_blk::ft1000_get_buffer NULL\n"); 2630 + } 2631 + } 2632 + else { 2633 + DEBUG("Out of memory in free receive command pool\n"); 2634 + info->app_info[i].nRxMsgMiss++; 2635 + }//endof if (pdpram_blk != NULL) 2636 + }//endof if 2637 + //else 2638 + // DEBUG("app_info mismatch\n"); 2639 + }// endof for 2640 + break; 2641 + default: 2642 + pdpram_blk = ft1000_get_buffer (&freercvpool); 2643 + //DEBUG("Memory allocated = 0x%8x\n", (u32)pdpram_blk); 2644 + if (pdpram_blk != NULL) { 2645 + if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE, &nxtph) ) { 2646 + ppseudo_hdr = (PPSEUDO_HDR)pdpram_blk->pbuffer; 2647 + // Search for correct application block 2648 + for (i=0; i<MAX_NUM_APP; i++) { 2649 + if (info->app_info[i].app_id == ppseudo_hdr->portdest) { 2650 + break; 2651 + } 2652 + } 2653 + 2654 + if (i==(MAX_NUM_APP-1)) { // aelias [+] reason: was out of array boundary 2655 + info->app_info[i].nRxMsgMiss++; 2656 + DEBUG("FT1000:ft1000_parse_dpram_msg: No application matching id = %d\n", ppseudo_hdr->portdest); 2657 + // Put memory back to free pool 2658 + ft1000_free_buffer(pdpram_blk, &freercvpool); 2659 + } 2660 + else { 2661 + if (info->app_info[i].NumOfMsg > MAX_MSG_LIMIT) { 2662 + // Put memory back to free pool 2663 + ft1000_free_buffer(pdpram_blk, &freercvpool); 2664 + } 2665 + else { 2666 + info->app_info[i].nRxMsg++; 2667 + // Put message into the appropriate application block 2668 + //pxu spin_lock_irqsave(&free_buff_lock, flags); 2669 + list_add_tail(&pdpram_blk->list, &info->app_info[i].app_sqlist); 2670 + info->app_info[i].NumOfMsg++; 2671 + //pxu spin_unlock_irqrestore(&free_buff_lock, flags); 2672 + //pxu wake_up_interruptible(&info->app_info[i].wait_dpram_msg); 2673 + } 2674 + } 2675 + } 2676 + else { 2677 + // Put memory back to free pool 2678 + ft1000_free_buffer(pdpram_blk, &freercvpool); 2679 + } 2680 + } 2681 + else { 2682 + DEBUG("Out of memory in free receive command pool\n"); 2683 + } 2684 + break; 2685 + } //end of switch 2686 + } //endof if (size < MAX_CMD_SQSIZE) 2687 + else { 2688 + DEBUG("FT1000:dpc:Invalid total length for SlowQ = %d\n", size); 2689 + } 2690 + status = ft1000_write_register (dev, FT1000_DB_DPRAM_RX, FT1000_REG_DOORBELL); 2691 + } 2692 + else if (tempword & FT1000_DSP_ASIC_RESET) { 2693 + //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DSP_ASIC_RESET\n"); 2694 + 2695 + // Let's reset the ASIC from the Host side as well 2696 + status = ft1000_write_register (dev, ASIC_RESET_BIT, FT1000_REG_RESET); 2697 + status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET); 2698 + i = 0; 2699 + while (tempword & ASIC_RESET_BIT) { 2700 + status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET); 2701 + msleep(10); 2702 + i++; 2703 + if (i==100) 2704 + break; 2705 + } 2706 + if (i==100) { 2707 + DEBUG("Unable to reset ASIC\n"); 2708 + return STATUS_SUCCESS; 2709 + } 2710 + msleep(10); 2711 + // Program WMARK register 2712 + status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK); 2713 + // clear ASIC reset doorbell 2714 + status = ft1000_write_register (dev, FT1000_DSP_ASIC_RESET, FT1000_REG_DOORBELL); 2715 + msleep(10); 2716 + } 2717 + else if (tempword & FT1000_ASIC_RESET_REQ) { 2718 + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n"); 2719 + 2720 + // clear ASIC reset request from DSP 2721 + status = ft1000_write_register (dev, FT1000_ASIC_RESET_REQ, FT1000_REG_DOORBELL); 2722 + status = ft1000_write_register (dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); 2723 + // copy dsp session record from Adapter block 2724 + status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&info->DSPSess.Rec[0], 1024); 2725 + // Program WMARK register 2726 + status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK); 2727 + // ring doorbell to tell DSP that ASIC is out of reset 2728 + status = ft1000_write_register (dev, FT1000_ASIC_RESET_DSP, FT1000_REG_DOORBELL); 2729 + } 2730 + else if (tempword & FT1000_DB_COND_RESET) { 2731 + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n"); 2732 + //By Jim 2733 + // Reset ASIC and DSP 2734 + //MAG 2735 + if (info->fAppMsgPend == 0) { 2736 + // Reset ASIC and DSP 2737 + 2738 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); 2739 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); 2740 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); 2741 + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); 2742 + info->CardReady = 0; 2743 + info->DrvErrNum = DSP_CONDRESET_INFO; 2744 + DEBUG("ft1000_hw:DSP conditional reset requested\n"); 2745 + info->ft1000_reset(dev->net); 2746 + } 2747 + else { 2748 + info->fProvComplete = 0; 2749 + info->fCondResetPend = 1; 2750 + } 2751 + 2752 + ft1000_write_register(dev, FT1000_DB_COND_RESET, FT1000_REG_DOORBELL); 2753 + } 2754 + 2755 + }//endof if ( !status ) 2756 + 2757 + //DEBUG("return from ft1000_poll.\n"); 2758 + return STATUS_SUCCESS; 2759 + 2760 + } 2761 + 2762 + /*end of Jim*/
+10
drivers/staging/ft1000/ft1000-usb/ft1000_hw.h
··· 1 + 2 + #ifndef _FT1000_HW_H_ 3 + #define _FT1000_HW_H_ 4 + 5 + #include "ft1000_usb.h" 6 + 7 + extern u16 ft1000_read_register(struct usb_device *dev, PUSHORT Data, u8 nRegIndx); 8 + extern u16 ft1000_write_register(struct usb_device *dev, USHORT value, u8 nRegIndx); 9 + 10 + #endif
+140
drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
··· 1 + //--------------------------------------------------------------------------- 2 + // FT1000 driver for Flarion Flash OFDM NIC Device 3 + // 4 + // Copyright (C) 2002 Flarion Technologies, All rights reserved. 5 + // 6 + // This program is free software; you can redistribute it and/or modify it 7 + // under the terms of the GNU General Public License as published by the Free 8 + // Software Foundation; either version 2 of the License, or (at your option) any 9 + // later version. This program is distributed in the hope that it will be useful, 10 + // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 + // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + // more details. You should have received a copy of the GNU General Public 13 + // License along with this program; if not, write to the 14 + // Free Software Foundation, Inc., 59 Temple Place - 15 + // Suite 330, Boston, MA 02111-1307, USA. 16 + //--------------------------------------------------------------------------- 17 + // 18 + // File: ft1000_ioctl.h 19 + // 20 + // Description: Common structures and defines relating to IOCTL 21 + // 22 + // History: 23 + // 11/5/02 Whc Created. 24 + // 25 + //---------------------------------------------------------------------------//--------------------------------------------------------------------------- 26 + #ifndef _FT1000IOCTLH_ 27 + #define _FT1000IOCTLH_ 28 + 29 + #define DSPVERSZ 4 30 + #define HWSERNUMSZ 16 31 + #define SKUSZ 20 32 + #define EUISZ 8 33 + #define CALVERSZ 2 34 + #define CALDATESZ 6 35 + 36 + #define MAX_DNLD_BLKSZ 1024 37 + 38 + // Standard Flarion Pseudo header 39 + typedef struct _PSEUDO_HDR 40 + { 41 + unsigned short length; //length of msg body 42 + unsigned char source; //source address (0x10=Host 0x20=DSP) 43 + unsigned char destination; //destination address (refer to source address) 44 + unsigned char portdest; //destination port id 45 + // 0x00=Driver 46 + // 0x10=Application Broadcast 47 + // 0x20=Network Stack 48 + // 0x80=Dsp OAM 49 + // 0x90=Dsp Airlink 50 + // 0xa0=Dsp Loader 51 + // 0xb0=Dsp MIP 52 + unsigned char portsrc; //source port id (refer to portdest) 53 + unsigned short sh_str_id; //stream id (Not applicable on Mobile) 54 + unsigned char control; //stream id (Not applicable on Mobile) 55 + unsigned char rsvd1; //reserved 56 + unsigned char seq_num; //sequence number 57 + unsigned char rsvd2; //reserved 58 + unsigned short qos_class; //Quality of Service class (Not applicable on Mobile) 59 + unsigned short checksum; //Psuedo header checksum 60 + } __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR; 61 + 62 + typedef struct _IOCTL_GET_VER 63 + { 64 + unsigned long drv_ver; 65 + } __attribute__ ((packed)) IOCTL_GET_VER, *PIOCTL_GET_VER; 66 + 67 + //Data structure for Dsp statistics 68 + typedef struct _IOCTL_GET_DSP_STAT 69 + { 70 + unsigned char DspVer[DSPVERSZ]; // DSP version number 71 + unsigned char HwSerNum[HWSERNUMSZ]; // Hardware Serial Number 72 + unsigned char Sku[SKUSZ]; // SKU 73 + unsigned char eui64[EUISZ]; // EUI64 74 + unsigned short ConStat; // Connection Status 75 + // Bits 0-3 = Connection Status Field 76 + // 0000=Idle (Disconnect) 77 + // 0001=Searching 78 + // 0010=Active (Connected) 79 + // 0011=Waiting for L2 down 80 + // 0100=Sleep 81 + unsigned short LedStat; // Led Status 82 + // Bits 0-3 = Signal Strength Field 83 + // 0000 = -105dBm to -92dBm 84 + // 0001 = -92dBm to -85dBm 85 + // 0011 = -85dBm to -75dBm 86 + // 0111 = -75dBm to -50dBm 87 + // 1111 = -50dBm to 0dBm 88 + // Bits 4-7 = Reserved 89 + // Bits 8-11 = SNR Field 90 + // 0000 = <2dB 91 + // 0001 = 2dB to 8dB 92 + // 0011 = 8dB to 15dB 93 + // 0111 = 15dB to 22dB 94 + // 1111 = >22dB 95 + // Bits 12-15 = Reserved 96 + unsigned long nTxPkts; // Number of packets transmitted from host to dsp 97 + unsigned long nRxPkts; // Number of packets received from dsp to host 98 + unsigned long nTxBytes; // Number of bytes transmitted from host to dsp 99 + unsigned long nRxBytes; // Number of bytes received from dsp to host 100 + unsigned long ConTm; // Current session connection time in seconds 101 + unsigned char CalVer[CALVERSZ]; // Proprietary Calibration Version 102 + unsigned char CalDate[CALDATESZ]; // Proprietary Calibration Date 103 + } __attribute__ ((packed)) IOCTL_GET_DSP_STAT, *PIOCTL_GET_DSP_STAT; 104 + 105 + //Data structure for Dual Ported RAM messaging between Host and Dsp 106 + typedef struct _IOCTL_DPRAM_BLK 107 + { 108 + unsigned short total_len; 109 + PSEUDO_HDR pseudohdr; 110 + unsigned char buffer[1780]; 111 + } __attribute__ ((packed)) IOCTL_DPRAM_BLK, *PIOCTL_DPRAM_BLK; 112 + 113 + typedef struct _IOCTL_DPRAM_COMMAND 114 + { 115 + unsigned short extra; 116 + IOCTL_DPRAM_BLK dpram_blk; 117 + } __attribute__ ((packed)) IOCTL_DPRAM_COMMAND, *PIOCTL_DPRAM_COMMAND; 118 + 119 + // 120 + // Custom IOCTL command codes 121 + // 122 + #define FT1000_MAGIC_CODE 'F' 123 + 124 + #define IOCTL_REGISTER_CMD 0 125 + #define IOCTL_SET_DPRAM_CMD 3 126 + #define IOCTL_GET_DPRAM_CMD 4 127 + #define IOCTL_GET_DSP_STAT_CMD 6 128 + #define IOCTL_GET_VER_CMD 7 129 + #define IOCTL_CONNECT 10 130 + #define IOCTL_DISCONNECT 11 131 + 132 + #define IOCTL_FT1000_GET_DSP_STAT _IOR (FT1000_MAGIC_CODE, IOCTL_GET_DSP_STAT_CMD, sizeof(IOCTL_GET_DSP_STAT) ) 133 + #define IOCTL_FT1000_GET_VER _IOR (FT1000_MAGIC_CODE, IOCTL_GET_VER_CMD, sizeof(IOCTL_GET_VER) ) 134 + #define IOCTL_FT1000_CONNECT _IOW (FT1000_MAGIC_CODE, IOCTL_CONNECT, 0 ) 135 + #define IOCTL_FT1000_DISCONNECT _IOW (FT1000_MAGIC_CODE, IOCTL_DISCONNECT, 0 ) 136 + #define IOCTL_FT1000_SET_DPRAM _IOW (FT1000_MAGIC_CODE, IOCTL_SET_DPRAM_CMD, sizeof(IOCTL_DPRAM_BLK) ) 137 + #define IOCTL_FT1000_GET_DPRAM _IOR (FT1000_MAGIC_CODE, IOCTL_GET_DPRAM_CMD, sizeof(IOCTL_DPRAM_BLK) ) 138 + #define IOCTL_FT1000_REGISTER _IOW (FT1000_MAGIC_CODE, IOCTL_REGISTER_CMD, sizeof(unsigned short *) ) 139 + #endif // _FT1000IOCTLH_ 140 +
+232
drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
··· 1 + #include <linux/module.h> 2 + #include <linux/kernel.h> 3 + #include <linux/proc_fs.h> 4 + #include <linux/netdevice.h> 5 + 6 + 7 + #include "ft1000_usb.h" 8 + 9 + #define FT1000_PROC_DIR "ft1000" 10 + 11 + 12 + #define PUTM_TO_PAGE(len,page,args...) \ 13 + len += snprintf(page+len, PAGE_SIZE - len, args) 14 + 15 + #define PUTX_TO_PAGE(len,page,message,size,var) \ 16 + len += snprintf(page+len, PAGE_SIZE - len, message); \ 17 + for(i = 0; i < (size - 1); i++) \ 18 + { \ 19 + len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \ 20 + } \ 21 + len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i]) 22 + 23 + #define PUTD_TO_PAGE(len,page,message,size,var) \ 24 + len += snprintf(page+len, PAGE_SIZE - len, message); \ 25 + for(i = 0; i < (size - 1); i++) \ 26 + { \ 27 + len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \ 28 + } \ 29 + len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i]) 30 + 31 + 32 + 33 + 34 + #ifdef INIT_NET_NS 35 + #define FTNET_PROC init_net.proc_net 36 + #else 37 + #define FTNET_PROC proc_net 38 + #endif 39 + 40 + 41 + u16 ft1000_read_dpram16 (struct ft1000_device *ft1000dev, USHORT indx, 42 + PUCHAR buffer, u8 highlow); 43 + 44 + 45 + int 46 + ft1000ReadProc (char *page, char **start, off_t off, int count, int *eof, 47 + void *data) 48 + { 49 + struct net_device *dev; 50 + int len; 51 + int i; 52 + unsigned short ledStat; 53 + unsigned short conStat; 54 + 55 + FT1000_INFO *info; 56 + 57 + char *status[] = { "Idle (Disconnect)", "Searching", "Active (Connected)", 58 + "Waiting for L2", "Sleep", "No Coverage", "", "" 59 + }; 60 + 61 + char *signal[] = { "", "*", "**", "***", "****" }; 62 + int strength; 63 + int quality; 64 + struct timeval tv; 65 + time_t delta; 66 + 67 + dev = (struct net_device *) data; 68 + info = (FT1000_INFO *) netdev_priv (dev); 69 + 70 + if (off > 0) 71 + { 72 + *eof = 1; 73 + return 0; 74 + } 75 + 76 + 77 + if (info->ProgConStat != 0xFF) 78 + { 79 + ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_LED, 80 + (PUCHAR) & ledStat, FT1000_MAG_DSP_LED_INDX); 81 + info->LedStat = ntohs (ledStat); 82 + 83 + ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_CON_STATE, 84 + (PUCHAR) & conStat, FT1000_MAG_DSP_CON_STATE_INDX); 85 + info->ConStat = ntohs (conStat); 86 + do_gettimeofday (&tv); 87 + delta = (tv.tv_sec - info->ConTm); 88 + } 89 + else 90 + { 91 + info->ConStat = 0xf; 92 + delta = 0; 93 + } 94 + 95 + 96 + 97 + i = (info->LedStat) & 0xf; 98 + switch (i) 99 + { 100 + case 0x1: 101 + strength = 1; 102 + break; 103 + case 0x3: 104 + strength = 2; 105 + break; 106 + case 0x7: 107 + strength = 3; 108 + break; 109 + case 0xf: 110 + strength = 4; 111 + break; 112 + default: 113 + strength = 0; 114 + } 115 + 116 + i = (info->LedStat >> 8) & 0xf; 117 + switch (i) 118 + { 119 + case 0x1: 120 + quality = 1; 121 + break; 122 + case 0x3: 123 + quality = 2; 124 + break; 125 + case 0x7: 126 + quality = 3; 127 + break; 128 + case 0xf: 129 + quality = 4; 130 + break; 131 + default: 132 + quality = 0; 133 + } 134 + 135 + 136 + len = 0; 137 + PUTM_TO_PAGE (len, page, "Connection Time: %02ld:%02ld:%02ld\n", 138 + ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60)); 139 + PUTM_TO_PAGE (len, page, "Connection Time[s]: %ld\n", delta); 140 + PUTM_TO_PAGE (len, page, "Asic ID: %s\n", 141 + (info->AsicID) == 142 + ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC"); 143 + PUTX_TO_PAGE (len, page, "SKU: ", SKUSZ, info->Sku); 144 + PUTX_TO_PAGE (len, page, "EUI64: ", EUISZ, info->eui64); 145 + PUTD_TO_PAGE (len, page, "DSP version number: ", DSPVERSZ, info->DspVer); 146 + PUTX_TO_PAGE (len, page, "Hardware Serial Number: ", HWSERNUMSZ, 147 + info->HwSerNum); 148 + PUTX_TO_PAGE (len, page, "Caliberation Version: ", CALVERSZ, 149 + info->RfCalVer); 150 + PUTD_TO_PAGE (len, page, "Caliberation Date: ", CALDATESZ, info->RfCalDate); 151 + PUTM_TO_PAGE (len, page, "Media State: %s\n", 152 + (info->mediastate) ? "link" : "no link"); 153 + PUTM_TO_PAGE (len, page, "Connection Status: %s\n", 154 + status[((info->ConStat) & 0x7)]); 155 + PUTM_TO_PAGE (len, page, "RX packets: %ld\n", info->stats.rx_packets); 156 + PUTM_TO_PAGE (len, page, "TX packets: %ld\n", info->stats.tx_packets); 157 + PUTM_TO_PAGE (len, page, "RX bytes: %ld\n", info->stats.rx_bytes); 158 + PUTM_TO_PAGE (len, page, "TX bytes: %ld\n", info->stats.tx_bytes); 159 + PUTM_TO_PAGE (len, page, "Signal Strength: %s\n", signal[strength]); 160 + PUTM_TO_PAGE (len, page, "Signal Quality: %s\n", signal[quality]); 161 + 162 + 163 + 164 + 165 + return len; 166 + } 167 + 168 + static int 169 + ft1000NotifyProc (struct notifier_block *this, unsigned long event, void *ptr) 170 + { 171 + struct net_device *dev = ptr; 172 + FT1000_INFO *info; 173 + struct proc_dir_entry *ft1000_proc_file; 174 + 175 + info = (FT1000_INFO *) netdev_priv (dev); 176 + 177 + 178 + switch (event) 179 + { 180 + case NETDEV_CHANGENAME: 181 + remove_proc_entry (info->netdevname, info->ft1000_proc_dir); 182 + ft1000_proc_file = create_proc_read_entry (dev->name, 0644, 183 + info->ft1000_proc_dir, 184 + ft1000ReadProc, dev); 185 + snprintf (info->netdevname, IFNAMSIZ, "%s", dev->name); 186 + break; 187 + } 188 + return NOTIFY_DONE; 189 + } 190 + 191 + static struct notifier_block ft1000_netdev_notifier = { 192 + .notifier_call = ft1000NotifyProc 193 + }; 194 + 195 + 196 + void 197 + ft1000InitProc (struct net_device *dev) 198 + { 199 + FT1000_INFO *info; 200 + struct proc_dir_entry *ft1000_proc_file; 201 + info = (FT1000_INFO *) netdev_priv (dev); 202 + 203 + 204 + info->ft1000_proc_dir = proc_mkdir (FT1000_PROC_DIR, FTNET_PROC); 205 + if (info->ft1000_proc_dir == NULL) 206 + { 207 + remove_proc_entry (FT1000_PROC_DIR, FTNET_PROC); 208 + } 209 + 210 + 211 + ft1000_proc_file = 212 + create_proc_read_entry (dev->name, 0644, info->ft1000_proc_dir, 213 + ft1000ReadProc, dev); 214 + if (ft1000_proc_file == NULL) 215 + { 216 + remove_proc_entry (info->netdevname, info->ft1000_proc_dir); 217 + } 218 + 219 + snprintf (info->netdevname, IFNAMSIZ, "%s", dev->name); 220 + register_netdevice_notifier (&ft1000_netdev_notifier); 221 + return; 222 + } 223 + 224 + void 225 + ft1000CleanupProc (FT1000_INFO * info) 226 + { 227 + remove_proc_entry (info->netdevname, info->ft1000_proc_dir); 228 + remove_proc_entry (FT1000_PROC_DIR, FTNET_PROC); 229 + unregister_netdevice_notifier (&ft1000_netdev_notifier); 230 + 231 + return; 232 + }
+349
drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
··· 1 + //===================================================== 2 + // CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. 3 + // 4 + // 5 + // This file is part of Express Card USB Driver 6 + // 7 + // $Id: 8 + //==================================================== 9 + // 20090926; aelias; removed all compiler warnings; ubuntu 9.04; 2.6.28-15-generic 10 + #include <linux/init.h> 11 + #include <linux/kernel.h> 12 + #include <linux/module.h> 13 + #include <linux/usb.h> 14 + #include <linux/netdevice.h> 15 + #include <linux/etherdevice.h> 16 + #include "ft1000_usb.h" 17 + 18 + //#include <linux/sched.h> 19 + //#include <linux/ptrace.h> 20 + //#include <linux/slab.h> 21 + //#include <linux/string.h> 22 + //#include <linux/timer.h> 23 + //#include <linux/netdevice.h> 24 + //#include <linux/ioport.h> 25 + //#include <linux/delay.h> 26 + //#include <asm/io.h> 27 + //#include <asm/system.h> 28 + #include <linux/kthread.h> 29 + 30 + MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER"); 31 + MODULE_LICENSE("Dual MPL/GPL"); 32 + MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards"); 33 + 34 + 35 + void *pFileStart; 36 + ULONG FileLength; 37 + 38 + #define VENDOR_ID 0x1291 /* Qualcomm vendor id */ 39 + #define PRODUCT_ID 0x11 /* fake product id */ 40 + 41 + /* table of devices that work with this driver */ 42 + static struct usb_device_id id_table[] = { 43 + {USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, 44 + { }, 45 + }; 46 + 47 + MODULE_DEVICE_TABLE (usb, id_table); 48 + 49 + extern struct ft1000_device *pdevobj[MAX_NUM_CARDS+2]; 50 + 51 + char *getfw (char *fn, int *pimgsz); 52 + 53 + int ft1000_close(struct net_device *net); 54 + void dsp_reload (struct ft1000_device *ft1000dev); 55 + u16 init_ft1000_netdev(struct ft1000_device *ft1000dev); 56 + u16 reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf); 57 + int ft1000_poll(void* dev_id); 58 + void ft1000_DestroyDevice(struct net_device *dev); 59 + u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow); 60 + u16 ft1000_read_register(struct ft1000_device *ft1000dev, short* Data, u16 nRegIndx); 61 + BOOLEAN gPollingfailed = FALSE; 62 + 63 + void ft1000InitProc(struct net_device *dev); 64 + void ft1000CleanupProc(FT1000_INFO *info); 65 + int ft1000_poll_thread(void *arg); 66 + 67 + int ft1000_poll_thread(void *arg) 68 + { 69 + int ret = STATUS_SUCCESS; 70 + 71 + while(!kthread_should_stop() ) 72 + { 73 + msleep(10); 74 + if ( ! gPollingfailed ) 75 + { 76 + ret = ft1000_poll(arg); 77 + if ( ret != STATUS_SUCCESS ) 78 + { 79 + DEBUG("ft1000_poll_thread: polling failed\n"); 80 + gPollingfailed = TRUE; 81 + } 82 + } 83 + } 84 + //DEBUG("returned from polling thread\n"); 85 + return STATUS_SUCCESS; 86 + } 87 + 88 + 89 + 90 + //--------------------------------------------------------------------------- 91 + // Function: ft1000_probe 92 + // 93 + // Parameters: struct usb_interface *interface - passed by USB core 94 + // struct usb_device_id *id - passed by USB core 95 + // Returns: 0 - success 96 + // 97 + // Description: This function is invoked when the express card is plugged in 98 + // 99 + // Notes: 100 + // 101 + //--------------------------------------------------------------------------- 102 + static int ft1000_probe(struct usb_interface *interface, const struct usb_device_id *id) 103 + { 104 + struct usb_host_interface *iface_desc; 105 + struct usb_endpoint_descriptor *endpoint; 106 + struct usb_device *dev; 107 + unsigned numaltsetting; 108 + int i; 109 + 110 + struct ft1000_device *ft1000dev; 111 + FT1000_INFO *pft1000info; 112 + 113 + if(!(ft1000dev = kmalloc(sizeof(struct ft1000_device), GFP_KERNEL))) 114 + { 115 + printk("out of memory allocating device structure\n"); 116 + return 0; 117 + } 118 + 119 + memset(ft1000dev, 0, sizeof(*ft1000dev)); 120 + 121 + //get usb device 122 + dev = interface_to_usbdev(interface); 123 + DEBUG("ft1000_probe: usb device descriptor info:\n"); 124 + DEBUG("ft1000_probe: number of configuration is %d\n", dev->descriptor.bNumConfigurations); 125 + 126 + ft1000dev->dev = dev; 127 + ft1000dev->status = 0; 128 + ft1000dev->net = NULL; 129 + //ft1000dev->device_lock = SPIN_LOCK_UNLOCKED; 130 + spin_lock_init(&ft1000dev->device_lock); 131 + ft1000dev->tx_urb = usb_alloc_urb(0, GFP_ATOMIC); 132 + ft1000dev->rx_urb = usb_alloc_urb(0, GFP_ATOMIC); 133 + 134 + 135 + DEBUG("ft1000_probe is called\n"); 136 + numaltsetting = interface->num_altsetting; 137 + DEBUG("ft1000_probe: number of alt settings is :%d\n",numaltsetting); 138 + iface_desc = interface->cur_altsetting; 139 + DEBUG("ft1000_probe: number of endpoints is %d\n", iface_desc->desc.bNumEndpoints); 140 + DEBUG("ft1000_probe: descriptor type is %d\n", iface_desc->desc.bDescriptorType); 141 + DEBUG("ft1000_probe: interface number is %d\n", iface_desc->desc.bInterfaceNumber); 142 + DEBUG("ft1000_probe: alternatesetting is %d\n", iface_desc->desc.bAlternateSetting); 143 + DEBUG("ft1000_probe: interface class is %d\n", iface_desc->desc.bInterfaceClass); 144 + DEBUG("ft1000_probe: control endpoint info:\n"); 145 + DEBUG("ft1000_probe: descriptor0 type -- %d\n", iface_desc->endpoint[0].desc.bmAttributes); 146 + DEBUG("ft1000_probe: descriptor1 type -- %d\n", iface_desc->endpoint[1].desc.bmAttributes); 147 + DEBUG("ft1000_probe: descriptor2 type -- %d\n", iface_desc->endpoint[2].desc.bmAttributes); 148 + 149 + for (i=0; i< iface_desc->desc.bNumEndpoints;i++ ) 150 + { 151 + endpoint = (struct usb_endpoint_descriptor *)&iface_desc->endpoint[i].desc; 152 + DEBUG("endpoint %d\n", i); 153 + DEBUG("bEndpointAddress=%x, bmAttributes=%x\n", endpoint->bEndpointAddress, endpoint->bmAttributes); 154 + if ( (endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) 155 + { 156 + ft1000dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; 157 + DEBUG("ft1000_probe: in: %d\n", endpoint->bEndpointAddress); 158 + } 159 + 160 + if (!(endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) 161 + { 162 + ft1000dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; 163 + DEBUG("ft1000_probe: out: %d\n", endpoint->bEndpointAddress); 164 + } 165 + } 166 + 167 + DEBUG("bulk_in=%d, bulk_out=%d\n", ft1000dev->bulk_in_endpointAddr, ft1000dev->bulk_out_endpointAddr); 168 + 169 + //read DSP image 170 + pFileStart = (void*)getfw("/etc/flarion/ft3000.img", &FileLength); 171 + 172 + if (pFileStart == NULL ) 173 + { 174 + DEBUG ("ft1000_probe: Read DSP image failed\n"); 175 + return 0; 176 + } 177 + 178 + //for ( i=0; i< MAX_NUM_CARDS+2; i++) 179 + // pdevobj[i] = NULL; 180 + 181 + //download dsp image 182 + DEBUG("ft1000_probe: start downloading dsp image...\n"); 183 + init_ft1000_netdev(ft1000dev); 184 + pft1000info = (FT1000_INFO *) netdev_priv (ft1000dev->net); 185 + 186 + // DEBUG("In probe: pft1000info=%x\n", pft1000info); // aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct FT1000_INFO *??? 187 + DEBUG("In probe: pft1000info=%x\n", (unsigned int)pft1000info); // aelias [+] reason: up 188 + 189 + dsp_reload(ft1000dev); 190 + gPollingfailed = FALSE; //mbelian 191 + pft1000info->pPollThread = kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll"); 192 + msleep(500); //mbelian 193 + 194 + 195 + if ( pft1000info->DSP_loading ) 196 + { 197 + DEBUG("ERROR!!!! RETURN FROM ft1000_probe **********************\n"); 198 + return 0; 199 + } 200 + 201 + while (!pft1000info->CardReady) 202 + { 203 + if ( gPollingfailed ) 204 + { 205 + if ( pft1000info->pPollThread ) 206 + { 207 + kthread_stop(pft1000info->pPollThread ); 208 + } 209 + return 0; 210 + } 211 + msleep(100); 212 + DEBUG("ft1000_probe::Waiting for Card Ready\n"); 213 + } 214 + 215 + 216 + //initialize network device 217 + DEBUG("ft1000_probe::Card Ready!!!! Registering network device\n"); 218 + 219 + reg_ft1000_netdev(ft1000dev, interface); 220 + 221 + pft1000info->NetDevRegDone = 1; 222 + 223 + ft1000InitProc(ft1000dev->net);// +mbelian 224 + 225 + return 0; 226 + } 227 + 228 + //--------------------------------------------------------------------------- 229 + // Function: ft1000_disconnect 230 + // 231 + // Parameters: struct usb_interface *interface - passed by USB core 232 + // 233 + // Returns: 0 - success 234 + // 235 + // Description: This function is invoked when the express card is plugged out 236 + // 237 + // Notes: 238 + // 239 + //--------------------------------------------------------------------------- 240 + static void ft1000_disconnect(struct usb_interface *interface) 241 + { 242 + FT1000_INFO *pft1000info; 243 + 244 + DEBUG("ft1000_disconnect is called\n"); 245 + 246 + pft1000info = (PFT1000_INFO)usb_get_intfdata(interface); 247 + // DEBUG("In disconnect pft1000info=%x\n", pft1000info); // aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct FT1000_INFO *??? 248 + DEBUG("In disconnect pft1000info=%x\n", (unsigned int) pft1000info); // aelias [+] reason: up 249 + 250 + 251 + 252 + if (pft1000info) 253 + { 254 + ft1000CleanupProc(pft1000info); //+mbelian 255 + if ( pft1000info->pPollThread ) 256 + { 257 + kthread_stop(pft1000info->pPollThread ); 258 + } 259 + 260 + DEBUG("ft1000_disconnect: threads are terminated\n"); 261 + 262 + if (pft1000info->pFt1000Dev->net) 263 + { 264 + DEBUG("ft1000_disconnect: destroy char driver\n"); 265 + ft1000_DestroyDevice(pft1000info->pFt1000Dev->net); 266 + //DEBUG("ft1000_disconnect: calling ft1000_close\n"); 267 + //ft1000_close(pft1000info->pFt1000Dev->net); 268 + //DEBUG("ft1000_disconnect: ft1000_close is called\n"); 269 + unregister_netdev(pft1000info->pFt1000Dev->net); 270 + DEBUG("ft1000_disconnect: network device unregisterd\n"); 271 + free_netdev(pft1000info->pFt1000Dev->net); 272 + 273 + } 274 + 275 + usb_free_urb(pft1000info->pFt1000Dev->rx_urb); 276 + usb_free_urb(pft1000info->pFt1000Dev->tx_urb); 277 + 278 + DEBUG("ft1000_disconnect: urb freed\n"); 279 + 280 + kfree(pft1000info->pFt1000Dev); //+mbelian 281 + } 282 + 283 + //terminate other kernel threads 284 + //in multiple instances case, first find the device 285 + //in the link list 286 + /**if (pPollThread) 287 + { 288 + kthread_stop(pPollThread); 289 + DEBUG("Polling thread is killed \n"); 290 + }**/ 291 + 292 + return; 293 + } 294 + 295 + static struct usb_driver ft1000_usb_driver = { 296 + //.owner = THIS_MODULE, 297 + .name = "ft1000usb", 298 + .probe = ft1000_probe, 299 + .disconnect = ft1000_disconnect, 300 + .id_table = id_table, 301 + }; 302 + 303 + //--------------------------------------------------------------------------- 304 + // Function: usb_ft1000_init 305 + // 306 + // Parameters: none 307 + // 308 + // Returns: 0 - success 309 + // 310 + // Description: The entry point of the module, register the usb driver 311 + // 312 + // Notes: 313 + // 314 + //--------------------------------------------------------------------------- 315 + static int __init usb_ft1000_init(void) 316 + { 317 + int ret = 0; 318 + 319 + DEBUG("Initialize and register the driver\n"); 320 + 321 + ret = usb_register(&ft1000_usb_driver); 322 + if (ret) 323 + err("usb_register failed. Error number %d", ret); 324 + 325 + return ret; 326 + } 327 + 328 + //--------------------------------------------------------------------------- 329 + // Function: usb_ft1000_exit 330 + // 331 + // Parameters: 332 + // 333 + // Returns: 334 + // 335 + // Description: Moudle unload function, deregister usb driver 336 + // 337 + // Notes: 338 + // 339 + //--------------------------------------------------------------------------- 340 + static void __exit usb_ft1000_exit(void) 341 + { 342 + DEBUG("Deregister the driver\n"); 343 + usb_deregister(&ft1000_usb_driver); 344 + } 345 + 346 + module_init (usb_ft1000_init); 347 + module_exit (usb_ft1000_exit); 348 + 349 +
+609
drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
··· 1 + #ifndef _FT1000_USB_H_ 2 + #define _FT1000_USB_H_ 3 + 4 + /*Jim*/ 5 + #include "ft1000_ioctl.h" 6 + #define FT1000_DRV_VER 0x01010403 7 + 8 + #define MODESZ 2 9 + #define MAX_NUM_APP 6 10 + #define MAX_MSG_LIMIT 200 11 + #define NUM_OF_FREE_BUFFERS 1500 12 + 13 + // Driver message types 14 + #define MEDIA_STATE 0x0010 15 + #define DSP_PROVISION 0x0030 16 + #define DSP_INIT_MSG 0x0050 17 + #define DSP_STORE_INFO 0x0070 18 + #define DSP_GET_INFO 0x0071 19 + #define GET_DRV_ERR_RPT_MSG 0x0073 20 + #define RSP_DRV_ERR_RPT_MSG 0x0074 21 + 22 + 23 + // Size of DPRAM Command 24 + #define MAX_CMD_SQSIZE 1780 25 + #define SLOWQ_TYPE 0 26 + #define PSEUDOSZ 16 27 + #define DSP_QID_OFFSET 4 28 + 29 + 30 + // MEMORY MAP FOR ELECTRABUZZ ASIC 31 + #define FT1000_REG_DFIFO_STAT 0x0008 // Downlink FIFO status register 32 + #define FT1000_REG_DPRAM_DATA 0x000C // DPRAM VALUE in DPRAM ADDR 33 + 34 + #define FT1000_DSP_LED 0xFFA // dsp led status for PAD device 35 + 36 + #define FT1000_MAG_DSP_LED 0x3FE // dsp led status for PAD device 37 + #define FT1000_MAG_DSP_LED_INDX 0x1 // dsp led status for PAD device 38 + 39 + #define SUCCESS 0x00 40 + 41 + 42 + #define DRIVERID 0x00 43 + 44 + // Driver Error Messages for DSP 45 + #define DSP_CONDRESET_INFO 0x7ef2 46 + #define DSP_HB_INFO 0x7ef0 47 + 48 + // Magnemite specific defines 49 + #define hi_mag 0x6968 // Byte swap hi to avoid additional system call 50 + #define ho_mag 0x6f68 // Byte swap ho to avoid additional system call 51 + 52 + 53 + 54 + typedef struct _MEDIAMSG { 55 + PSEUDO_HDR pseudo; 56 + u16 type; 57 + u16 length; 58 + u16 state; 59 + u32 ip_addr; 60 + u32 net_mask; 61 + u32 gateway; 62 + u32 dns_1; 63 + u32 dns_2; 64 + } __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG; 65 + 66 + typedef struct _DSPINITMSG { 67 + PSEUDO_HDR pseudo; 68 + u16 type; 69 + u16 length; 70 + u8 DspVer[DSPVERSZ]; // DSP version number 71 + u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number 72 + u8 Sku[SKUSZ]; // SKU 73 + u8 eui64[EUISZ]; // EUI64 74 + u8 ProductMode[MODESZ]; // Product Mode (Market/Production) 75 + u8 RfCalVer[CALVERSZ]; // Rf Calibration version 76 + u8 RfCalDate[CALDATESZ]; // Rf Calibration date 77 + } __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG; 78 + 79 + 80 + typedef struct _APP_INFO_BLOCK 81 + { 82 + u32 nTxMsg; // DPRAM msg sent to DSP with app_id 83 + u32 nRxMsg; // DPRAM msg rcv from dsp with app_id 84 + u32 nTxMsgReject; // DPRAM msg rejected due to DSP doorbell set 85 + u32 nRxMsgMiss; // DPRAM msg dropped due to overflow 86 + u32 fileobject; // Application's file object 87 + u16 app_id; // Application id 88 + int DspBCMsgFlag; 89 + int NumOfMsg; // number of messages queued up 90 + wait_queue_head_t wait_dpram_msg; 91 + struct list_head app_sqlist; // link list of msgs for applicaton on slow queue 92 + } APP_INFO_BLOCK, *PAPP_INFO_BLOCK; 93 + 94 + typedef struct _PROV_RECORD { 95 + struct list_head list; 96 + u8 *pprov_data; 97 + } PROV_RECORD, *PPROV_RECORD; 98 + 99 + /*end of Jim*/ 100 + 101 + #define DEBUG(args...) printk(KERN_INFO args) 102 + 103 + #define UCHAR u8 104 + #define USHORT u16 105 + #define ULONG u32 106 + #define BOOLEAN u8 107 + #define PULONG u32 * 108 + #define PUSHORT u16 * 109 + #define PUCHAR u8 * 110 + #define PCHAR u8 * 111 + #define UINT u32 112 + 113 + #define FALSE 0 114 + #define TRUE 1 115 + 116 + #define STATUS_SUCCESS 0 117 + #define STATUS_FAILURE 0x1001 118 + 119 + #define FT1000_STATUS_CLOSING 0x01 120 + 121 + #define LARGE_TIMEOUT 5000 122 + 123 + #define MAX_DSP_SESS_REC 1024 124 + 125 + #define MAX_NUM_CARDS 32 126 + 127 + #define DSPVERSZ 4 128 + #define HWSERNUMSZ 16 129 + #define SKUSZ 20 130 + #define EUISZ 8 131 + #define CALVERSZ 2 132 + #define CALDATESZ 6 133 + #define MODESZ 2 134 + 135 + #define DSPID 0x20 136 + #define HOSTID 0x10 137 + 138 + #define DSPOAM 0x80 139 + #define DSPAIRID 0x90 140 + 141 + #define DRIVERID 0x00 142 + #define FMM 0x10 143 + #define NETWORKID 0x20 144 + #define AUTOLNCHID 0x30 145 + #define DSPLPBKID 0x40 146 + 147 + #define DSPBCMSGID 0x10 148 + 149 + #define ENET_MAX_SIZE 1514 150 + #define ENET_HEADER_SIZE 14 151 + 152 + 153 + #define CIS_NET_ADDR_OFFSET 0xff0 154 + 155 + #define MEM_TAG 'FLRN' 156 + // MAGNEMITE specific 157 + 158 + #define FT1000_REG_MAG_UFDR 0x0000 // Uplink FIFO Data Register. 159 + 160 + #define FT1000_REG_MAG_UFDRL 0x0000 // Uplink FIFO Data Register low-word. 161 + 162 + #define FT1000_REG_MAG_UFDRH 0x0002 // Uplink FIFO Data Register high-word. 163 + 164 + #define FT1000_REG_MAG_UFER 0x0004 // Uplink FIFO End Register 165 + 166 + #define FT1000_REG_MAG_UFSR 0x0006 // Uplink FIFO Status Register 167 + 168 + #define FT1000_REG_MAG_DFR 0x0008 // Downlink FIFO Register 169 + 170 + #define FT1000_REG_MAG_DFRL 0x0008 // Downlink FIFO Register low-word 171 + 172 + #define FT1000_REG_MAG_DFRH 0x000a // Downlink FIFO Register high-word 173 + 174 + #define FT1000_REG_MAG_DFSR 0x000c // Downlink FIFO Status Register 175 + 176 + #define FT1000_REG_MAG_DPDATA 0x0010 // Dual Port RAM Indirect Data Register 177 + 178 + #define FT1000_REG_MAG_DPDATAL 0x0010 // Dual Port RAM Indirect Data Register low-word 179 + 180 + #define FT1000_REG_MAG_DPDATAH 0x0012 // Dual Port RAM Indirect Data Register high-word 181 + 182 + #define FT1000_REG_MAG_WATERMARK 0x002c // Supv. Control Reg. LLC register 183 + 184 + #define FT1000_REG_MAG_VERSION 0x0030 // LLC Version LLC register 185 + 186 + 187 + 188 + // Common 189 + 190 + #define FT1000_REG_DPRAM_ADDR 0x000E // DPRAM ADDRESS when card in IO mode 191 + 192 + #define FT1000_REG_SUP_CTRL 0x0020 // Supv. Control Reg. LLC register 193 + 194 + #define FT1000_REG_SUP_STAT 0x0022 // Supv. Status Reg LLC register 195 + 196 + #define FT1000_REG_RESET 0x0024 // Reset Reg LLC register 197 + 198 + #define FT1000_REG_SUP_ISR 0x0026 // Supv ISR LLC register 199 + 200 + #define FT1000_REG_SUP_IMASK 0x0028 // Supervisor Interrupt Mask LLC register 201 + 202 + #define FT1000_REG_DOORBELL 0x002a // Door Bell Reg LLC register 203 + 204 + #define FT1000_REG_ASIC_ID 0x002e // ASIC Identification Number 205 + 206 + // (Electrabuzz=0 Magnemite=TBD) 207 + 208 + 209 + 210 + // DSP doorbells 211 + 212 + #define FT1000_DB_DPRAM_RX 0x0001 // this value indicates that DSP has 213 + 214 + // data for host in DPRAM SlowQ 215 + 216 + #define FT1000_DB_DNLD_RX 0x0002 // Downloader handshake doorbell 217 + 218 + #define FT1000_ASIC_RESET_REQ 0x0004 219 + 220 + #define FT1000_DSP_ASIC_RESET 0x0008 221 + 222 + 223 + 224 + #define FT1000_DB_COND_RESET 0x0010 225 + 226 + 227 + 228 + // Host doorbells 229 + 230 + #define FT1000_DB_DPRAM_TX 0x0100 // this value indicates that host has 231 + 232 + // data for DSP in DPRAM. 233 + 234 + #define FT1000_DB_DNLD_TX 0x0200 // Downloader handshake doorbell 235 + 236 + #define FT1000_ASIC_RESET_DSP 0x0400 237 + 238 + #define FT1000_DB_HB 0x1000 // this value indicates that supervisor 239 + 240 + 241 + 242 + // Electrabuzz specific DPRAM mapping // has a heartbeat message for DSP. 243 + 244 + #define FT1000_DPRAM_BASE 0x1000 // 0x0000 to 0x07FF DPRAM 2Kx16 - R/W from PCMCIA or DSP 245 + 246 + #define FT1000_DPRAM_TX_BASE 0x1002 // TX AREA (SlowQ) 247 + 248 + #define FT1000_DPRAM_RX_BASE 0x1800 // RX AREA (SlowQ) 249 + 250 + #define FT1000_DPRAM_SIZE 0x1000 // 4K bytes 251 + 252 + 253 + 254 + #define FT1000_DRV_DEBUG 0x17E0 // Debug area for driver 255 + 256 + #define FT1000_FIFO_LEN 0x17FC // total length for DSP FIFO tracking 257 + 258 + #define FT1000_HI_HO 0x17FE // heartbeat with HI/HO 259 + 260 + #define FT1000_DSP_STATUS 0x1FFE // dsp status - non-zero is a request to reset dsp 261 + 262 + 263 + 264 + #define FT1000_DSP_CON_STATE 0x1FF8 // DSP Connection Status Info 265 + 266 + #define FT1000_DSP_LEDS 0x1FFA // DSP LEDS for rcv pwr strength, Rx data, Tx data 267 + 268 + #define DSP_TIMESTAMP 0x1FFC // dsp timestamp 269 + 270 + #define DSP_TIMESTAMP_DIFF 0x1FFA // difference of dsp timestamp in DPRAM and Pseudo header. 271 + 272 + 273 + 274 + #define FT1000_DPRAM_FEFE 0x1002 // Dsp Downloader handshake location 275 + 276 + 277 + 278 + #define FT1000_DSP_TIMER0 0x1FF0 279 + 280 + #define FT1000_DSP_TIMER1 0x1FF2 281 + 282 + #define FT1000_DSP_TIMER2 0x1FF4 283 + 284 + #define FT1000_DSP_TIMER3 0x1FF6 285 + 286 + 287 + 288 + // MEMORY MAP FOR MAGNEMITE 289 + 290 + #define FT1000_DPRAM_MAG_TX_BASE 0x0000 // TX AREA (SlowQ) 291 + 292 + #define FT1000_DPRAM_MAG_RX_BASE 0x0200 // RX AREA (SlowQ) 293 + 294 + 295 + 296 + #define FT1000_MAG_FIFO_LEN 0x1FF // total length for DSP FIFO tracking 297 + 298 + #define FT1000_MAG_FIFO_LEN_INDX 0x1 // low-word index 299 + 300 + #define FT1000_MAG_HI_HO 0x1FF // heartbeat with HI/HO 301 + 302 + #define FT1000_MAG_HI_HO_INDX 0x0 // high-word index 303 + 304 + #define FT1000_MAG_DSP_LEDS 0x3FE // dsp led status for PAD device 305 + 306 + #define FT1000_MAG_DSP_LEDS_INDX 0x1 // dsp led status for PAD device 307 + 308 + 309 + 310 + #define FT1000_MAG_DSP_CON_STATE 0x3FE // DSP Connection Status Info 311 + 312 + #define FT1000_MAG_DSP_CON_STATE_INDX 0x0 // DSP Connection Status Info 313 + 314 + 315 + 316 + #define FT1000_MAG_DPRAM_FEFE 0x000 // location for dsp ready indicator 317 + 318 + #define FT1000_MAG_DPRAM_FEFE_INDX 0x0 // location for dsp ready indicator 319 + 320 + 321 + 322 + #define FT1000_MAG_DSP_TIMER0 0x3FC 323 + 324 + #define FT1000_MAG_DSP_TIMER0_INDX 0x1 325 + 326 + 327 + 328 + #define FT1000_MAG_DSP_TIMER1 0x3FC 329 + 330 + #define FT1000_MAG_DSP_TIMER1_INDX 0x0 331 + 332 + 333 + 334 + #define FT1000_MAG_DSP_TIMER2 0x3FD 335 + 336 + #define FT1000_MAG_DSP_TIMER2_INDX 0x1 337 + 338 + 339 + 340 + #define FT1000_MAG_DSP_TIMER3 0x3FD 341 + 342 + #define FT1000_MAG_DSP_TIMER3_INDX 0x0 343 + 344 + 345 + 346 + #define FT1000_MAG_TOTAL_LEN 0x200 347 + 348 + #define FT1000_MAG_TOTAL_LEN_INDX 0x1 349 + 350 + 351 + 352 + #define FT1000_MAG_PH_LEN 0x200 353 + 354 + #define FT1000_MAG_PH_LEN_INDX 0x0 355 + 356 + 357 + 358 + #define FT1000_MAG_PORT_ID 0x201 359 + 360 + #define FT1000_MAG_PORT_ID_INDX 0x0 361 + 362 + 363 + 364 + // 365 + 366 + // Constants for the FT1000_REG_SUP_ISR 367 + 368 + // 369 + 370 + // Indicate the cause of an interrupt. 371 + 372 + // 373 + 374 + // SUPERVISOR ISR BIT MAPS 375 + 376 + 377 + 378 + #define ISR_EMPTY (UCHAR)0x00 // no bits set in ISR 379 + 380 + #define ISR_DOORBELL_ACK (UCHAR)0x01 // the doorbell i sent has been recieved. 381 + 382 + #define ISR_DOORBELL_PEND (UCHAR)0x02 // doorbell for me 383 + 384 + #define ISR_RCV (UCHAR)0x04 // packet received with no errors 385 + 386 + #define ISR_WATERMARK (UCHAR)0x08 // 387 + 388 + 389 + 390 + // Interrupt mask register defines 391 + 392 + // note these are different from the ISR BIT MAPS. 393 + 394 + #define ISR_MASK_NONE 0x0000 395 + 396 + #define ISR_MASK_DOORBELL_ACK 0x0001 397 + 398 + #define ISR_MASK_DOORBELL_PEND 0x0002 399 + 400 + #define ISR_MASK_RCV 0x0004 401 + 402 + #define ISR_MASK_WATERMARK 0x0008 // Normally we will only mask the watermark interrupt when we want to enable interrupts. 403 + 404 + #define ISR_MASK_ALL 0xffff 405 + 406 + 407 + 408 + #define HOST_INTF_LE 0x0000 // Host interface little endian 409 + 410 + #define HOST_INTF_BE 0x0001 // Host interface big endian 411 + 412 + 413 + 414 + #define ISR_DEFAULT_MASK 0x7ff9 415 + 416 + 417 + 418 + #define hi 0x6869 419 + 420 + #define ho 0x686f 421 + 422 + 423 + 424 + #define FT1000_ASIC_RESET 0x80 // COR value for soft reset to PCMCIA core 425 + 426 + #define FT1000_ASIC_BITS 0x51 // Bits set in COR register under normal operation 427 + 428 + #define FT1000_ASIC_MAG_BITS 0x55 // Bits set in COR register under normal operation 429 + 430 + 431 + 432 + #define FT1000_COR_OFFSET 0x100 433 + 434 + 435 + 436 + #define ELECTRABUZZ_ID 0 // ASIC ID for ELECTRABUZZ 437 + 438 + #define MAGNEMITE_ID 0x1a01 // ASIC ID for MAGNEMITE 439 + 440 + 441 + 442 + // Maximum times trying to get ASIC out of reset 443 + 444 + #define MAX_ASIC_RESET_CNT 20 445 + 446 + 447 + 448 + #define DSP_RESET_BIT 0x1 449 + 450 + #define ASIC_RESET_BIT 0x2 451 + 452 + #define DSP_UNENCRYPTED 0x4 453 + 454 + #define DSP_ENCRYPTED 0x8 455 + 456 + #define EFUSE_MEM_DISABLE 0x0040 457 + 458 + 459 + #define MAX_BUF_SIZE 4096 460 + 461 + 462 + #if 0 //Removed by Jim 463 + typedef struct _PSEUDO_HDR 464 + 465 + { 466 + 467 + unsigned short length; 468 + 469 + unsigned char source; 470 + 471 + unsigned char destination; 472 + 473 + unsigned char portdest; 474 + 475 + unsigned char portsrc; 476 + 477 + unsigned short sh_str_id; 478 + 479 + unsigned char control; 480 + 481 + unsigned char rsvd1; 482 + 483 + unsigned char seq_num; 484 + 485 + unsigned char rsvd2; 486 + 487 + unsigned short qos_class; 488 + 489 + unsigned short checksum; 490 + 491 + 492 + 493 + } PSEUDO_HDR, *PPSEUDO_HDR; 494 + #endif //end of Jim 495 + 496 + typedef struct _DRVMSG { 497 + PSEUDO_HDR pseudo; 498 + u16 type; 499 + u16 length; 500 + u8 data[0]; 501 + } __attribute__ ((packed)) DRVMSG, *PDRVMSG; 502 + 503 + struct ft1000_device 504 + { 505 + struct usb_device *dev; 506 + struct net_device *net; 507 + spinlock_t device_lock; 508 + 509 + u32 status; 510 + 511 + wait_queue_head_t control_wait; 512 + 513 + struct urb *rx_urb; 514 + struct urb *tx_urb; 515 + 516 + u8 tx_buf[MAX_BUF_SIZE]; 517 + u8 rx_buf[MAX_BUF_SIZE]; 518 + 519 + u8 bulk_in_endpointAddr; 520 + u8 bulk_out_endpointAddr; 521 + 522 + //struct ft1000_ethernet_configuration configuration; 523 + 524 + // struct net_device_stats stats; //mbelian 525 + } __attribute__ ((packed)); 526 + 527 + typedef struct _FT1000_INFO { 528 + struct ft1000_device *pFt1000Dev; 529 + struct net_device_stats stats; 530 + 531 + struct task_struct *pPollThread; 532 + 533 + unsigned char fcodeldr; 534 + unsigned char bootmode; 535 + unsigned char usbboot; 536 + unsigned short dspalive; 537 + u16 ASIC_ID; 538 + BOOLEAN fProvComplete; 539 + BOOLEAN fCondResetPend; 540 + BOOLEAN fAppMsgPend; 541 + char *pfwimg; 542 + int fwimgsz; 543 + u16 DrvErrNum; 544 + u8 *pTestImage; 545 + u16 AsicID; 546 + unsigned long TestImageIndx; 547 + unsigned long TestImageSz; 548 + u8 TestImageEnable; 549 + u8 TestImageReady; 550 + int ASICResetNum; 551 + int DspAsicReset; 552 + int PktIntfErr; 553 + int DSPResetNum; 554 + int NumIOCTLBufs; 555 + int IOCTLBufLvl; 556 + int DeviceCreated; 557 + int CardReady; 558 + int DSP_loading; 559 + int NetDevRegDone; 560 + u8 CardNumber; 561 + u8 DeviceName[15]; 562 + int DeviceMajor; 563 + int registered; 564 + int mediastate; 565 + int dhcpflg; 566 + u16 packetseqnum; 567 + u8 squeseqnum; // sequence number on slow queue 568 + spinlock_t dpram_lock; 569 + spinlock_t fifo_lock; 570 + u16 CurrentInterruptEnableMask; 571 + int InterruptsEnabled; 572 + u16 fifo_cnt; 573 + u8 DspVer[DSPVERSZ]; // DSP version number 574 + u8 HwSerNum[HWSERNUMSZ]; // Hardware Serial Number 575 + u8 Sku[SKUSZ]; // SKU 576 + u8 eui64[EUISZ]; // EUI64 577 + time_t ConTm; // Connection Time 578 + u8 ProductMode[MODESZ]; 579 + u8 RfCalVer[CALVERSZ]; 580 + u8 RfCalDate[CALDATESZ]; 581 + u16 DSP_TIME[4]; 582 + u16 ProgSnr; 583 + u16 LedStat; //mbelian 584 + u16 ConStat; //mbelian 585 + u16 ProgConStat; 586 + struct list_head prov_list; 587 + int appcnt; 588 + APP_INFO_BLOCK app_info[MAX_NUM_APP]; //Added by Jim 589 + u16 DSPInfoBlklen; 590 + u16 DrvMsgPend; 591 + int (*ft1000_reset)(struct net_device *dev); 592 + u16 DSPInfoBlk[MAX_DSP_SESS_REC]; 593 + union { 594 + u16 Rec[MAX_DSP_SESS_REC]; 595 + u32 MagRec[MAX_DSP_SESS_REC/2]; 596 + } DSPSess; 597 + unsigned short tempbuf[32]; 598 + char netdevname[IFNAMSIZ]; 599 + struct proc_dir_entry *ft1000_proc_dir; //mbelian 600 + } FT1000_INFO, *PFT1000_INFO; 601 + 602 + 603 + typedef struct _DPRAM_BLK { 604 + struct list_head list; 605 + u16 *pbuffer; 606 + } __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK; 607 + 608 + 609 + #endif
drivers/staging/ft1000/ft1000-usb/ft3000.img

This is a binary file and will not be displayed.