Date:2011-11-06 16:01:46 (12 years 4 months ago)
Author:Xiangfu Liu
Commit:dc637c92b654be23167417ab4fc8712733e498d1
Message:xburst: ben nanonote: first add WPAN(atben,atusb) driver take from qi-kernel.git thanks to Werner

Files: target/linux/xburst/patches-3.0/0001-JZ4740-cache-quirks.patch (1 diff)
target/linux/xburst/patches-3.0/0002-Add-n516-board-support.patch (1 diff)
target/linux/xburst/patches-3.0/0003-Add-n526-board-support.patch (1 diff)
target/linux/xburst/patches-3.0/0004-MIPS-JZ4740-Add-id800wt-board.patch (1 diff)
target/linux/xburst/patches-3.0/0005-Add-N516-sound-SoC-board-driver.patch (1 diff)
target/linux/xburst/patches-3.0/0006-Add-n516-lpc-driver.patch (1 diff)
target/linux/xburst/patches-3.0/0007-Add-N526-sound-SoC-board-driver.patch (1 diff)
target/linux/xburst/patches-3.0/0008-i2c-Add-i2c-driver-for-JZ47XX-SoCs.patch (1 diff)
target/linux/xburst/patches-3.0/0009-MIPS-JZ4740-Fix-i2c-driver-name.patch (1 diff)
target/linux/xburst/patches-3.0/0010-MFD-jz4740-adc-Add-support-for-the-touchscreen-part-.patch (1 diff)
target/linux/xburst/patches-3.0/0011-input-Add-touchscreen-driver-for-the-JZ4740-SoC.patch (1 diff)
target/linux/xburst/patches-3.0/0012-Add-ili8960-lcd-driver.patch (1 diff)
target/linux/xburst/patches-3.0/0013-Add-jz4740-udc-driver.patch (1 diff)
target/linux/xburst/patches-3.0/0014-Framebuffer-notifier-Call-notifier-callbacks-prior-t.patch (1 diff)
target/linux/xburst/patches-3.0/0015-500-modifier-keys.patch.patch (1 diff)
target/linux/xburst/patches-3.0/0016-850-ks7010-support.patch.patch (1 diff)
target/linux/xburst/patches-3.0/0017-900-add-openwrt-logo.patch (1 diff)
target/linux/xburst/patches-3.0/0018-901-ubi-Read-only-the-vid-header-instead-of-the-whol.patch (1 diff)
target/linux/xburst/patches-3.0/0019-902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch.patch (1 diff)
target/linux/xburst/patches-3.0/0020-903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_.patch (1 diff)
target/linux/xburst/patches-3.0/0021-904-NAND-Optimize-reading-the-eec-data-for-the-JZ474.patch (1 diff)
target/linux/xburst/patches-3.0/0022-qi_lb60-Don-t-use-3-wire-spi-mode-for-the-display-fo.patch (1 diff)
target/linux/xburst/patches-3.0/0023-qi_lb60-NAND-add-data-partition.patch (1 diff)
target/linux/xburst/patches-3.0/0024-forward-code-to-linux-3.0.patch (1 diff)
target/linux/xburst/patches-3.0/0025-Update-to-new-platform-code.patch (1 diff)
target/linux/xburst/patches-3.0/0026-sound-update-DMA-code.patch (1 diff)
target/linux/xburst/patches-3.0/0027-Add-DEVMEM-support.patch (1 diff)
target/linux/xburst/patches-3.0/0028-Add-cpufreq-support.patch (1 diff)
target/linux/xburst/patches-3.0/0029-Add-new-jz4740_lcd.h.patch (1 diff)
target/linux/xburst/patches-3.0/0030-fbcon-color-fonts.patch (13 diffs)
target/linux/xburst/patches-3.0/0031-first-patch-for-atBen.patch (1 diff)
target/linux/xburst/patches-3.0/0032-set-atben-GPIO-to-func_none.patch (1 diff)

Change Details

target/linux/xburst/patches-3.0/0001-JZ4740-cache-quirks.patch
11From 2f669aa98831b7248402bab6a07b1b6f722cb6e9 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sat, 24 Apr 2010 17:34:29 +0200
4Subject: [PATCH 01/29] JZ4740 cache quirks
4Subject: [PATCH 01/32] JZ4740 cache quirks
55
66---
77 arch/mips/include/asm/r4kcache.h | 231 ++++++++++++++++++++++++++++++++++++++
target/linux/xburst/patches-3.0/0002-Add-n516-board-support.patch
11From 633a1f02f183675e3448c45a5ddd5e942ecbc37c Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sat, 24 Apr 2010 17:25:01 +0200
4Subject: [PATCH 02/29] Add n516 board support
4Subject: [PATCH 02/32] Add n516 board support
55
66---
77 arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++
target/linux/xburst/patches-3.0/0003-Add-n526-board-support.patch
11From dcc0d9f15146c100a843dfa62ba259e208330f07 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sat, 24 Apr 2010 17:25:23 +0200
4Subject: [PATCH 03/29] Add n526 board support
4Subject: [PATCH 03/32] Add n526 board support
55
66---
77 arch/mips/jz4740/Kconfig | 4 +
target/linux/xburst/patches-3.0/0004-MIPS-JZ4740-Add-id800wt-board.patch
11From 322d8e1ccf544f576d60622dc304f136cef64a3b Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 5 Sep 2010 20:34:08 +0200
4Subject: [PATCH 04/29] MIPS: JZ4740: Add id800wt board
4Subject: [PATCH 04/32] MIPS: JZ4740: Add id800wt board
55
66---
77 arch/mips/jz4740/Kconfig | 4 +
target/linux/xburst/patches-3.0/0005-Add-N516-sound-SoC-board-driver.patch
11From 523f9ca02b5c2c8b79f1d01fff03b1191a6aed6c Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 1 Aug 2010 21:34:54 +0200
4Subject: [PATCH 05/29] Add N516 sound SoC board driver
4Subject: [PATCH 05/32] Add N516 sound SoC board driver
55
66---
77 sound/soc/jz4740/Kconfig | 8 ++
target/linux/xburst/patches-3.0/0006-Add-n516-lpc-driver.patch
11From b02e39f1ba2310fedf212d2a6e5d99c4a14fc297 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Wed, 12 May 2010 14:22:36 +0200
4Subject: [PATCH 06/29] Add n516 lpc driver
4Subject: [PATCH 06/32] Add n516 lpc driver
55
66---
77 drivers/misc/Kconfig | 8 +
target/linux/xburst/patches-3.0/0007-Add-N526-sound-SoC-board-driver.patch
11From 19d5c8c334a79951d927a1b6eb25bf6a896c9ab5 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sat, 24 Apr 2010 12:38:41 +0200
4Subject: [PATCH 07/29] Add N526 sound SoC board driver
4Subject: [PATCH 07/32] Add N526 sound SoC board driver
55
66---
77 sound/soc/jz4740/Kconfig | 8 ++
target/linux/xburst/patches-3.0/0008-i2c-Add-i2c-driver-for-JZ47XX-SoCs.patch
11From 5e219770079a61b8c8e59abe5510678361c94696 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 5 Sep 2010 03:19:10 +0200
4Subject: [PATCH 08/29] i2c: Add i2c driver for JZ47XX SoCs
4Subject: [PATCH 08/32] i2c: Add i2c driver for JZ47XX SoCs
55
66This patch adds a driver for the i2c controller found in Ingenic JZ47XX based
77SoCs.
target/linux/xburst/patches-3.0/0009-MIPS-JZ4740-Fix-i2c-driver-name.patch
11From 05bc4140f9da08fa48d81131ffa785e3026773a8 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 5 Sep 2010 03:21:51 +0200
4Subject: [PATCH 09/29] MIPS: JZ4740: Fix i2c driver name.
4Subject: [PATCH 09/32] MIPS: JZ4740: Fix i2c driver name.
55
66The i2c driver is generic to all JZ47XX based SoCs not only the JZ4740. Reflect
77this in the driver name.
target/linux/xburst/patches-3.0/0010-MFD-jz4740-adc-Add-support-for-the-touchscreen-part-.patch
11From 659b0bb01c8e567d4593ffbd7acd6b8ceab0edf3 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 5 Sep 2010 20:36:59 +0200
4Subject: [PATCH 10/29] MFD: jz4740-adc: Add support for the touchscreen part of the adc unit
4Subject: [PATCH 10/32] MFD: jz4740-adc: Add support for the touchscreen part of the adc unit
55
66---
77 drivers/mfd/jz4740-adc.c | 27 ++++++++++++++++++++++++---
target/linux/xburst/patches-3.0/0011-input-Add-touchscreen-driver-for-the-JZ4740-SoC.patch
11From 71e0648ad022c6f05e1bed1fcca69abc8abde4d9 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 5 Sep 2010 20:45:08 +0200
4Subject: [PATCH 11/29] input: Add touchscreen driver for the JZ4740 SoC
4Subject: [PATCH 11/32] input: Add touchscreen driver for the JZ4740 SoC
55
66This patch adds a touchscreen driver for the Ingenic JZ4740 SoC.
77The touchscreen controller is part of the ADC unit and thus this driver is a mfd
target/linux/xburst/patches-3.0/0012-Add-ili8960-lcd-driver.patch
11From d7a92f8ccdca40672a2a242c756fb52c31b2bdba Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sun, 1 Aug 2010 21:19:40 +0200
4Subject: [PATCH 12/29] Add ili8960 lcd driver
4Subject: [PATCH 12/32] Add ili8960 lcd driver
55
66---
77 drivers/video/backlight/Kconfig | 7 +
target/linux/xburst/patches-3.0/0013-Add-jz4740-udc-driver.patch
11From ecd72bc68f9b9a39cb0f1ec456787c61f03be978 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Tue, 13 Sep 2011 16:07:41 +0800
4Subject: [PATCH 13/29] Add jz4740 udc driver
4Subject: [PATCH 13/32] Add jz4740 udc driver
55
66---
77 drivers/usb/gadget/Kconfig | 13 +
target/linux/xburst/patches-3.0/0014-Framebuffer-notifier-Call-notifier-callbacks-prior-t.patch
11From c7700fa672bf0a171ceb9f4b092de33e3b306243 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Sat, 24 Apr 2010 12:23:28 +0200
4Subject: [PATCH 14/29] Framebuffer notifier: Call notifier callbacks prior to blanking the screen
4Subject: [PATCH 14/32] Framebuffer notifier: Call notifier callbacks prior to blanking the screen
55
66---
77 drivers/video/fbmem.c | 8 ++++++--
target/linux/xburst/patches-3.0/0015-500-modifier-keys.patch.patch
11From 15bd698ca3f4104f3e3c28dcc7619dcef21f40ad Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:40:08 +0800
4Subject: [PATCH 15/29] 500-modifier-keys.patch
4Subject: [PATCH 15/32] 500-modifier-keys.patch
55
66---
77 drivers/tty/vt/defkeymap.c_shipped | 326 +++++++++++++++++++++++++++---------
target/linux/xburst/patches-3.0/0016-850-ks7010-support.patch.patch
11From f4c9a977dc405856676cd1ca435394faf49b5f1c Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:44:15 +0800
4Subject: [PATCH 16/29] 850-ks7010-support.patch
4Subject: [PATCH 16/32] 850-ks7010-support.patch
55
66---
77 drivers/mmc/core/core.c | 4 ++--
target/linux/xburst/patches-3.0/0017-900-add-openwrt-logo.patch
11From a5d4cdf6165b2e324f6f55a0c6b2e3d29d303382 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Wed, 12 May 2010 14:18:47 +0200
4Subject: [PATCH 17/29] 900-add-openwrt-logo
4Subject: [PATCH 17/32] 900-add-openwrt-logo
55
66---
77 drivers/video/logo/Kconfig | 4 +
target/linux/xburst/patches-3.0/0018-901-ubi-Read-only-the-vid-header-instead-of-the-whol.patch
11From e4334870d2348cc326cb9135e9da83cdbec9e95e Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:45:19 +0800
4Subject: [PATCH 18/29] 901-ubi-Read-only-the-vid-header-instead-of-the-whole-pa.patch
4Subject: [PATCH 18/32] 901-ubi-Read-only-the-vid-header-instead-of-the-whole-pa.patch
55
66---
77 drivers/mtd/ubi/io.c | 2 +-
target/linux/xburst/patches-3.0/0019-902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch.patch
11From a525f2fabe86dfd4a1acc057afcb31de319ca3e5 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:45:39 +0800
4Subject: [PATCH 19/29] 902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch
4Subject: [PATCH 19/32] 902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch
55
66---
77 drivers/mtd/nand/nand_base.c | 14 ++++++++++----
target/linux/xburst/patches-3.0/0020-903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_.patch
11From e4e1ca7caccf399366d8dbbf6539217e2c7ea852 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:45:59 +0800
4Subject: [PATCH 20/29] 903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_HW_O.patch
4Subject: [PATCH 20/32] 903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_HW_O.patch
55
66---
77 drivers/mtd/nand/nand_base.c | 78 ++++++++++++++++++++++++++++++++++++++++--
target/linux/xburst/patches-3.0/0021-904-NAND-Optimize-reading-the-eec-data-for-the-JZ474.patch
11From 5fa159fe903240a78136ba90bfefc91d899fcfe3 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:46:14 +0800
4Subject: [PATCH 21/29] 904-NAND-Optimize-reading-the-eec-data-for-the-JZ4740-ev.patch
4Subject: [PATCH 21/32] 904-NAND-Optimize-reading-the-eec-data-for-the-JZ4740-ev.patch
55
66---
77 drivers/mtd/nand/nand_base.c | 14 ++++----------
target/linux/xburst/patches-3.0/0022-qi_lb60-Don-t-use-3-wire-spi-mode-for-the-display-fo.patch
11From 1133e48ddc4c3082dfa78606cff16d3c3bde84c4 Mon Sep 17 00:00:00 2001
22From: Lars-Peter Clausen <lars@metafoo.de>
33Date: Wed, 13 Oct 2010 01:17:24 +0200
4Subject: [PATCH 22/29] qi_lb60: Don't use 3-wire spi mode for the display for now
4Subject: [PATCH 22/32] qi_lb60: Don't use 3-wire spi mode for the display for now
55
66The spi_gpio driver does not support 3-wire mode.
77---
target/linux/xburst/patches-3.0/0023-qi_lb60-NAND-add-data-partition.patch
11From 1878b22649c3ecde1795d6695b92ca02fa9110c2 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.(none)>
33Date: Fri, 19 Aug 2011 15:46:52 +0800
4Subject: [PATCH 23/29] qi_lb60: NAND: add data partition
4Subject: [PATCH 23/32] qi_lb60: NAND: add data partition
55
66---
77 arch/mips/jz4740/board-qi_lb60.c | 7 ++++++-
target/linux/xburst/patches-3.0/0024-forward-code-to-linux-3.0.patch
11From 87eb40e63e1b149ef87fe05765b97328bfbd1c1f Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Wed, 14 Sep 2011 14:29:37 +0800
4Subject: [PATCH 24/29] forward code to linux 3.0
4Subject: [PATCH 24/32] forward code to linux 3.0
55
66---
77 arch/mips/Kconfig | 2 +
target/linux/xburst/patches-3.0/0025-Update-to-new-platform-code.patch
11From 8a760f273f94b72e882d7f82b04ade72ae739a6b Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@sharism.cc>
33Date: Wed, 14 Sep 2011 15:12:41 +0800
4Subject: [PATCH 25/29] Update to new platform code
4Subject: [PATCH 25/32] Update to new platform code
55
66---
77 drivers/mtd/nand/jz4740_nand.c | 2 +-
target/linux/xburst/patches-3.0/0026-sound-update-DMA-code.patch
11From 5e689acca07bccdced123f82e8dde5459eca0d97 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Wed, 14 Sep 2011 14:30:01 +0800
4Subject: [PATCH 26/29] sound: update DMA code
4Subject: [PATCH 26/32] sound: update DMA code
55
66---
77 sound/soc/jz4740/jz4740-pcm.c | 21 ++++++++++++++++++---
target/linux/xburst/patches-3.0/0027-Add-DEVMEM-support.patch
11From ab59753a9df09b990822b15d2593c5c98905684c Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Wed, 14 Sep 2011 14:29:51 +0800
4Subject: [PATCH 27/29] Add DEVMEM support
4Subject: [PATCH 27/32] Add DEVMEM support
55
66---
77 drivers/char/Kconfig | 10 ++++++++++
target/linux/xburst/patches-3.0/0028-Add-cpufreq-support.patch
11From b0b7794018b75ce33be133664fb58ab3e6efc2e8 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Wed, 14 Sep 2011 14:29:52 +0800
4Subject: [PATCH 28/29] Add cpufreq support
4Subject: [PATCH 28/32] Add cpufreq support
55
66---
77 drivers/cpufreq/cpufreq_stats.c | 161 ++++++++++++++++++++-------------------
target/linux/xburst/patches-3.0/0029-Add-new-jz4740_lcd.h.patch
11From 2dc84f90409839e6a85bd9e25394a387c86d12a1 Mon Sep 17 00:00:00 2001
22From: Xiangfu Liu <xiangfu@macbook.openmobilefree.net>
33Date: Wed, 14 Sep 2011 14:29:58 +0800
4Subject: [PATCH 29/29] Add new jz4740_lcd.h
4Subject: [PATCH 29/32] Add new jz4740_lcd.h
55
66---
77 drivers/video/jz4740_fb.c | 78 +----------------------------------
target/linux/xburst/patches-3.0/0030-fbcon-color-fonts.patch
1From 77de829067262bbe1f7435b087c11ad9a8ea0b06 Mon Sep 17 00:00:00 2001
2From: Xiangfu Liu <xiangfu@sharism.cc>
3Date: Tue, 18 Oct 2011 09:21:04 +0800
4Subject: [PATCH 30/32] fbcon-color-fonts
5
6---
7 drivers/tty/vt/vt.c | 3 +-
8 drivers/video/console/bitblit.c | 188 +++++++++++++++++++++++++++++++++------
9 drivers/video/console/fbcon.c | 14 +++-
10 3 files changed, 173 insertions(+), 32 deletions(-)
11
12diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
13index b3915b7..37eaac5 100644
114--- a/drivers/tty/vt/vt.c
215+++ b/drivers/tty/vt/vt.c
3@@ -4034,6 +4034,7 @@ static int con_font_set(struct vc_data *
16@@ -4034,6 +4034,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
417     struct console_font font;
518     int rc = -EINVAL;
619     int size;
...... 
821
922     if (vc->vc_mode != KD_TEXT)
1023         return -EINVAL;
11@@ -4063,7 +4064,7 @@ static int con_font_set(struct vc_data *
24@@ -4063,7 +4064,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
1225     }
1326     if (op->width <= 0 || op->width > 32 || op->height > 32)
1427         return -EINVAL;
...... 
1730     if (size > max_font_size)
1831         return -ENOSPC;
1932     font.charcount = op->charcount;
33diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
34index 28b1a83..8e559df 100644
2035--- a/drivers/video/console/bitblit.c
2136+++ b/drivers/video/console/bitblit.c
22@@ -105,6 +105,12 @@ static inline void bit_putcs_aligned(str
37@@ -105,6 +105,12 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
2338     info->fbops->fb_imageblit(info, image);
2439 }
2540
...... 
3247 static inline void bit_putcs_unaligned(struct vc_data *vc,
3348                        struct fb_info *info, const u16 *s,
3449                        u32 attr, u32 cnt, u32 d_pitch,
35@@ -140,12 +146,62 @@ static inline void bit_putcs_unaligned(s
50@@ -140,12 +146,62 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
3651
3752 }
3853
...... 
96111     u32 cellsize = width * vc->vc_font.height;
97112     u32 maxcnt = info->pixmap.size/cellsize;
98113     u32 scan_align = info->pixmap.scan_align - 1;
99@@ -153,6 +209,10 @@ static void bit_putcs(struct vc_data *vc
114@@ -153,6 +209,10 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
100115     u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
101116     u32 attribute = get_attribute(info, scr_readw(s));
102117     u8 *dst, *buf = NULL;
...... 
107122
108123     image.fg_color = fg;
109124     image.bg_color = bg;
110@@ -167,31 +227,73 @@ static void bit_putcs(struct vc_data *vc
125@@ -167,31 +227,73 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
111126             return;
112127     }
113128
...... 
206221     }
207222
208223     /* buf is always NULL except when in monochrome mode, so in this case
209@@ -234,6 +336,29 @@ static void bit_clear_margins(struct vc_
224@@ -234,6 +336,29 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
210225     }
211226 }
212227
...... 
236251 static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
237252                int softback_lines, int fg, int bg)
238253 {
239@@ -245,6 +370,7 @@ static void bit_cursor(struct vc_data *v
254@@ -245,6 +370,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
240255     int attribute, use_sw = (vc->vc_cursor_type & 0x10);
241256     int err = 1;
242257     char *src;
...... 
244259
245260     cursor.set = 0;
246261
247@@ -383,8 +509,14 @@ static void bit_cursor(struct vc_data *v
262@@ -383,8 +509,14 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
248263     if (info->fbops->fb_cursor)
249264         err = info->fbops->fb_cursor(info, &cursor);
250265
...... 
261276
262277     ops->cursor_reset = 0;
263278 }
279diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
280index 8745637..dea9d2c 100644
264281--- a/drivers/video/console/fbcon.c
265282+++ b/drivers/video/console/fbcon.c
266@@ -2552,7 +2552,8 @@ static int fbcon_set_font(struct vc_data
283@@ -2552,7 +2552,8 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
267284     int size;
268285     int i, csum;
269286     u8 *new_data, *data = font->data;
...... 
273290
274291     /* Is there a reason why fbconsole couldn't handle any charcount >256?
275292      * If not this check should be changed to charcount < 256 */
276@@ -2571,6 +2572,7 @@ static int fbcon_set_font(struct vc_data
293@@ -2571,6 +2572,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
277294     size = h * pitch * charcount;
278295
279296     new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
...... 
281298
282299     if (!new_data)
283300         return -ENOMEM;
284@@ -2579,8 +2581,14 @@ static int fbcon_set_font(struct vc_data
301@@ -2579,8 +2581,14 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
285302     FNTSIZE(new_data) = size;
286303     FNTCHARCNT(new_data) = charcount;
287304     REFCOUNT(new_data) = 0; /* usage counter */
...... 
298315     }
299316
300317     /* Since linux has a nice crc32 function use it for counting font
318--
3191.7.4.1
320
target/linux/xburst/patches-3.0/0031-first-patch-for-atBen.patch
1From 84f38ed9a131b807927e4aed2f277d8a2fad5286 Mon Sep 17 00:00:00 2001
2From: Xiangfu Liu <xiangfu@sharism.cc>
3Date: Wed, 19 Oct 2011 10:59:47 +0800
4Subject: [PATCH 31/32] first patch for atBen
5
6---
7 drivers/ieee802154/Kconfig | 55 ++-
8 drivers/ieee802154/Makefile | 10 +-
9 drivers/ieee802154/adf7242.c | 1034 ++++++++++++++++++++++++++++++++++++++
10 drivers/ieee802154/at86rf230.c | 872 ++++++++++++++++++++++++++++++++
11 drivers/ieee802154/at86rf230.h | 211 ++++++++
12 drivers/ieee802154/cc2420.c | 859 ++++++++++++++++++++++++++++++++
13 drivers/ieee802154/fakehard.c | 14 +-
14 drivers/ieee802154/fakelb.c | 311 ++++++++++++
15 drivers/ieee802154/serial.c | 1047 +++++++++++++++++++++++++++++++++++++++
16 drivers/ieee802154/spi_atben.c | 421 ++++++++++++++++
17 drivers/ieee802154/spi_atusb.c | 750 ++++++++++++++++++++++++++++
18 include/linux/if.h | 2 +
19 include/linux/if_arp.h | 2 +
20 include/linux/if_ieee802154.h | 6 +
21 include/linux/nl802154.h | 10 +-
22 include/linux/spi/at86rf230.h | 34 ++
23 include/net/ieee802154_netdev.h | 17 +-
24 include/net/mac802154.h | 156 ++++++
25 include/net/wpan-phy.h | 8 +-
26 net/Kconfig | 2 +
27 net/Makefile | 1 +
28 net/ieee802154/Kconfig | 9 +
29 net/ieee802154/Makefile | 3 +
30 net/ieee802154/dgram.c | 3 +-
31 net/ieee802154/ieee802154.h | 4 +
32 net/ieee802154/nl-mac.c | 2 +-
33 net/ieee802154/nl-phy.c | 48 ++-
34 net/ieee802154/nl_policy.c | 1 +
35 net/ieee802154/wpan-class.c | 2 +-
36 net/mac802154/Kconfig | 24 +
37 net/mac802154/Makefile | 6 +
38 net/mac802154/beacon.c | 282 +++++++++++
39 net/mac802154/beacon_hash.c | 106 ++++
40 net/mac802154/beacon_hash.h | 41 ++
41 net/mac802154/mac802154.h | 126 +++++
42 net/mac802154/mac_cmd.c | 362 ++++++++++++++
43 net/mac802154/main.c | 282 +++++++++++
44 net/mac802154/mib.c | 249 ++++++++++
45 net/mac802154/mib.h | 35 ++
46 net/mac802154/monitor.c | 116 +++++
47 net/mac802154/rx.c | 117 +++++
48 net/mac802154/scan.c | 203 ++++++++
49 net/mac802154/smac.c | 127 +++++
50 net/mac802154/tx.c | 106 ++++
51 net/mac802154/wpan.c | 630 +++++++++++++++++++++++
52 net/zigbee/Kconfig | 7 +
53 net/zigbee/Makefile | 5 +
54 net/zigbee/af_zigbee.c | 285 +++++++++++
55 net/zigbee/dgram.c | 401 +++++++++++++++
56 49 files changed, 9380 insertions(+), 24 deletions(-)
57 create mode 100644 drivers/ieee802154/adf7242.c
58 create mode 100644 drivers/ieee802154/at86rf230.c
59 create mode 100644 drivers/ieee802154/at86rf230.h
60 create mode 100644 drivers/ieee802154/cc2420.c
61 create mode 100644 drivers/ieee802154/fakelb.c
62 create mode 100644 drivers/ieee802154/serial.c
63 create mode 100644 drivers/ieee802154/spi_atben.c
64 create mode 100644 drivers/ieee802154/spi_atusb.c
65 create mode 100644 include/linux/if_ieee802154.h
66 create mode 100644 include/linux/spi/at86rf230.h
67 create mode 100644 include/net/mac802154.h
68 create mode 100644 net/mac802154/Kconfig
69 create mode 100644 net/mac802154/Makefile
70 create mode 100644 net/mac802154/beacon.c
71 create mode 100644 net/mac802154/beacon_hash.c
72 create mode 100644 net/mac802154/beacon_hash.h
73 create mode 100644 net/mac802154/mac802154.h
74 create mode 100644 net/mac802154/mac_cmd.c
75 create mode 100644 net/mac802154/main.c
76 create mode 100644 net/mac802154/mib.c
77 create mode 100644 net/mac802154/mib.h
78 create mode 100644 net/mac802154/monitor.c
79 create mode 100644 net/mac802154/rx.c
80 create mode 100644 net/mac802154/scan.c
81 create mode 100644 net/mac802154/smac.c
82 create mode 100644 net/mac802154/tx.c
83 create mode 100644 net/mac802154/wpan.c
84 create mode 100644 net/zigbee/Kconfig
85 create mode 100644 net/zigbee/Makefile
86 create mode 100644 net/zigbee/af_zigbee.c
87 create mode 100644 net/zigbee/dgram.c
88
89diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig
90index 9b9f43a..a323dc1 100644
91--- a/drivers/ieee802154/Kconfig
92@@ -10,13 +10,64 @@ menuconfig IEEE802154_DRIVERS
93       If you say N, all options in this submenu will be skipped and
94       disabled.
95
96+config IEEE802154_DRIVER_DEBUG
97+ bool "Driver debugging messages"
98+ depends on IEEE802154_DRIVERS
99+ default y
100+ help
101+ Say Y here to make the IEEE 802.15.4 drivers generate extensive
102+ debugging messages.
103+
104 config IEEE802154_FAKEHARD
105     tristate "Fake LR-WPAN driver with several interconnected devices"
106     depends on IEEE802154_DRIVERS
107     ---help---
108       Say Y here to enable the fake driver that serves as an example
109- of HardMAC device driver.
110+ of HardMAC device driver.
111
112- This driver can also be built as a module. To do so say M here.
113+ This driver can also be built as a module. To do so say M here.
114       The module will be called 'fakehard'.
115
116+
117+config IEEE802154_FAKELB
118+ depends on IEEE802154_DRIVERS && MAC802154
119+ tristate "Fake LR-WPAN driver with several interconnected devices"
120+ ---help---
121+ Say Y here to enable the fake driver that can emulate a net
122+ of several interconnected radio devices.
123+
124+ This driver can also be built as a module. To do so say M here.
125+ The module will be called 'fakelb'.
126+
127+config IEEE802154_SERIAL
128+ depends on IEEE802154_DRIVERS && MAC802154
129+ tristate "Simple LR-WPAN UART driver"
130+
131+config IEEE802154_AT86RF230
132+ depends on IEEE802154_DRIVERS && MAC802154
133+ tristate "AT86RF230 transceiver driver"
134+ depends on SPI
135+
136+config SPI_ATBEN
137+ tristate "ATBEN 8:10 SPI interface"
138+ depends on JZ4740_QI_LB60 && IEEE802154_AT86RF230
139+ help
140+ Bit-banging SPI driver for the 8:10 interface of the Ben NanoNote
141+ when equipped with an ATBEN board.
142+
143+config SPI_ATUSB
144+ tristate "ATUSB SPI interface"
145+ depends on USB && IEEE802154_AT86RF230
146+ help
147+ SPI-over-USB driver for the ATUSB IEEE 802.15.4 board.
148+
149+config IEEE802154_CC2420
150+ tristate "CC2420 driver"
151+ depends on SPI
152+ depends on IEEE802154_DRIVERS
153+
154+config IEEE802154_ADF7242
155+ tristate "ADF7242 transceiver driver"
156+ depends on IEEE802154_DRIVERS && MAC802154
157+ depends on SPI
158+
159diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
160index 6899913..2a10a6a 100644
161--- a/drivers/ieee802154/Makefile
162@@ -1,3 +1,11 @@
163 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
164+obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
165+obj-$(CONFIG_IEEE802154_SERIAL) += serial.o
166+obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
167+obj-$(CONFIG_IEEE802154_CC2420) += cc2420.o
168+obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
169+obj-$(CONFIG_SPI_ATUSB) += spi_atusb.o
170+obj-$(CONFIG_SPI_ATBEN) += spi_atben.o
171
172-ccflags-y := -DDEBUG -DCONFIG_FFD
173+ccflags-$(CONFIG_IEEE802154_DRIVER_DEBUG) += -DDEBUG
174+ccflags-y += -DCONFIG_FFD
175diff --git a/drivers/ieee802154/adf7242.c b/drivers/ieee802154/adf7242.c
176new file mode 100644
177index 0000000..b578a55
178--- /dev/null
179@@ -0,0 +1,1034 @@
180+/*
181+ * Analog Devices ADF7242 Low-Power IEEE 802.15.4 Transceiver
182+ *
183+ * Copyright 2009-2010 Analog Devices Inc.
184+ *
185+ * Licensed under the GPL-2 or later.
186+ */
187+
188+#include <linux/kernel.h>
189+#include <linux/module.h>
190+#include <linux/interrupt.h>
191+#include <linux/delay.h>
192+#include <linux/mutex.h>
193+#include <linux/workqueue.h>
194+#include <linux/spinlock.h>
195+#include <linux/firmware.h>
196+#include <linux/spi/spi.h>
197+#include <linux/spi/adf7242.h>
198+
199+#include <net/mac802154.h>
200+#include <net/wpan-phy.h>
201+
202+/*
203+ * DEBUG LEVEL
204+ * 0 OFF
205+ * 1 INFO
206+ * 2 INFO + TRACE
207+ */
208+
209+#define ADF_DEBUG 0
210+#define DBG(n, args...) do { if (ADF_DEBUG >= (n)) pr_debug(args); } while (0)
211+
212+#define FIRMWARE "adf7242_firmware.bin"
213+#define MAX_POLL_LOOPS 10
214+
215+/* All Registers */
216+
217+#define REG_EXT_CTRL 0x100 /* RW External LNA/PA and internal PA control configuration bits */
218+#define REG_TX_FSK_TEST 0x101 /* RW TX FSK test mode configuration */
219+#define REG_CCA1 0x105 /* RW RSSI threshold for CCA */
220+#define REG_CCA2 0x106 /* RW CCA mode configuration */
221+#define REG_BUFFERCFG 0x107 /* RW RX_BUFFER overwrite control */
222+#define REG_PKT_CFG 0x108 /* RW FCS evaluation configuration */
223+#define REG_DELAYCFG0 0x109 /* RW RC_RX command to SFD or sync word search delay */
224+#define REG_DELAYCFG1 0x10A /* RW RC_TX command to TX state */
225+#define REG_DELAYCFG2 0x10B /* RW Mac delay extention */
226+#define REG_SYNC_WORD0 0x10C /* RW sync word bits [7:0] of [23:0] */
227+#define REG_SYNC_WORD1 0x10D /* RW sync word bits [15:8] of [23:0] */
228+#define REG_SYNC_WORD2 0x10E /* RW sync word bits [23:16] of [23:0] */
229+#define REG_SYNC_CONFIG 0x10F /* RW sync word configuration */
230+#define REG_RC_CFG 0x13E /* RW RX / TX packet configuration */
231+#define REG_RC_VAR44 0x13F /* RW RESERVED */
232+#define REG_CH_FREQ0 0x300 /* RW Channel Frequency Settings - Low Byte */
233+#define REG_CH_FREQ1 0x301 /* RW Channel Frequency Settings - Middle Byte */
234+#define REG_CH_FREQ2 0x302 /* RW Channel Frequency Settings - 2 MSBs */
235+#define REG_TX_FD 0x304 /* RW TX Frequency Deviation Register */
236+#define REG_DM_CFG0 0x305 /* RW RX Discriminator BW Register */
237+#define REG_TX_M 0x306 /* RW TX Mode Register */
238+#define REG_RX_M 0x307 /* RW RX Mode Register */
239+#define REG_RRB 0x30C /* R RSSI Readback Register */
240+#define REG_LRB 0x30D /* R Link Quality Readback Register */
241+#define REG_DR0 0x30E /* RW bits [15:8] of [15:0] for data rate setting */
242+#define REG_DR1 0x30F /* RW bits [7:0] of [15:0] for data rate setting */
243+#define REG_PRAMPG 0x313 /* RW RESERVED */
244+#define REG_TXPB 0x314 /* RW TX Packet Storage Base Address */
245+#define REG_RXPB 0x315 /* RW RX Packet Storage Base Address */
246+#define REG_TMR_CFG0 0x316 /* RW Wake up Timer Configuration Register - High Byte */
247+#define REG_TMR_CFG1 0x317 /* RW Wake up Timer Configuration Register - Low Byte */
248+#define REG_TMR_RLD0 0x318 /* RW Wake up Timer Value Register - High Byte */
249+#define REG_TMR_RLD1 0x319 /* RW Wake up Timer Value Register - Low Byte */
250+#define REG_TMR_CTRL 0x31A /* RW Wake up Timer Timeout flag */
251+#define REG_PD_AUX 0x31E /* RW Battmon enable */
252+#define REG_GP_CFG 0x32C /* RW GPIO Configuration */
253+#define REG_GP_OUT 0x32D /* RW GPIO Configuration */
254+#define REG_GP_IN 0x32E /* R GPIO Configuration */
255+#define REG_SYNT 0x335 /* RW bandwidth calibration timers */
256+#define REG_CAL_CFG 0x33D /* RW Calibration Settings */
257+#define REG_SYNT_CAL 0x371 /* RW Oscillator and Doubler Configuration */
258+#define REG_IIRF_CFG 0x389 /* RW BB Filter Decimation Rate */
259+#define REG_CDR_CFG 0x38A /* RW CDR kVCO */
260+#define REG_DM_CFG1 0x38B /* RW Postdemodulator Filter */
261+#define REG_AGCSTAT 0x38E /* R RXBB Ref Osc Calibration Engine Readback */
262+#define REG_RXCAL0 0x395 /* RW RX BB filter tuning, LSB */
263+#define REG_RXCAL1 0x396 /* RW RX BB filter tuning, MSB */
264+#define REG_RXFE_CFG 0x39B /* RW RXBB Ref Osc & RXFE Calibration */
265+#define REG_PA_RR 0x3A7 /* RW Set PA ramp rate */
266+#define REG_PA_CFG 0x3A8 /* RW PA enable */
267+#define REG_EXTPA_CFG 0x3A9 /* RW External PA BIAS DAC */
268+#define REG_EXTPA_MSC 0x3AA /* RW PA Bias Mode */
269+#define REG_ADC_RBK 0x3AE /* R Readback temp */
270+#define REG_AGC_CFG1 0x3B2 /* RW GC Parameters */
271+#define REG_AGC_MAX 0x3B4 /* RW Slew rate */
272+#define REG_AGC_CFG2 0x3B6 /* RW RSSI Parameters */
273+#define REG_AGC_CFG3 0x3B7 /* RW RSSI Parameters */
274+#define REG_AGC_CFG4 0x3B8 /* RW RSSI Parameters */
275+#define REG_AGC_CFG5 0x3B9 /* RW RSSI & NDEC Parameters */
276+#define REG_AGC_CFG6 0x3BA /* RW NDEC Parameters */
277+#define REG_OCL_CFG1 0x3C4 /* RW OCL System Parameters */
278+#define REG_IRQ1_EN0 0x3C7 /* RW Interrupt Mask set bits [7:0] of [15:0] for IRQ1 */
279+#define REG_IRQ1_EN1 0x3C8 /* RW Interrupt Mask set bits [15:8] of [15:0] for IRQ1 */
280+#define REG_IRQ2_EN0 0x3C9 /* RW Interrupt Mask set bits [7:0] of [15:0] for IRQ2 */
281+#define REG_IRQ2_EN1 0x3CA /* RW Interrupt Mask set bits [15:8] of [15:0] for IRQ2 */
282+#define REG_IRQ1_SRC0 0x3CB /* RW Interrupt Source bits [7:0] of [15:0] for IRQ */
283+#define REG_IRQ1_SRC1 0x3CC /* RW Interrupt Source bits [15:8] of [15:0] for IRQ */
284+#define REG_OCL_BW0 0x3D2 /* RW OCL System Parameters */
285+#define REG_OCL_BW1 0x3D3 /* RW OCL System Parameters */
286+#define REG_OCL_BW2 0x3D4 /* RW OCL System Parameters */
287+#define REG_OCL_BW3 0x3D5 /* RW OCL System Parameters */
288+#define REG_OCL_BW4 0x3D6 /* RW OCL System Parameters */
289+#define REG_OCL_BWS 0x3D7 /* RW OCL System Parameters */
290+#define REG_OCL_CFG13 0x3E0 /* RW OCL System Parameters */
291+#define REG_GP_DRV 0x3E3 /* RW I/O pads Configuration and bg trim */
292+#define REG_BM_CFG 0x3E6 /* RW Battery Monitor Threshold Voltage setting */
293+#define REG_SFD_15_4 0x3F4 /* RW Option to set non standard SFD */
294+#define REG_AFC_CFG 0x3F7 /* RW AFC mode and polarity */
295+#define REG_AFC_KI_KP 0x3F8 /* RW AFC ki and kp */
296+#define REG_AFC_RANGE 0x3F9 /* RW AFC range */
297+#define REG_AFC_READ 0x3FA /* RW Readback frequency error */
298+
299+#define REG_PAN_ID0 0x112
300+#define REG_PAN_ID1 0x113
301+#define REG_SHORT_ADDR_0 0x114
302+#define REG_SHORT_ADDR_1 0x115
303+#define REG_IEEE_ADDR_0 0x116
304+#define REG_IEEE_ADDR_1 0x117
305+#define REG_IEEE_ADDR_2 0x118
306+#define REG_IEEE_ADDR_3 0x119
307+#define REG_IEEE_ADDR_4 0x11A
308+#define REG_IEEE_ADDR_5 0x11B
309+#define REG_IEEE_ADDR_6 0x11C
310+#define REG_IEEE_ADDR_7 0x11D
311+#define REG_FFILT_CFG 0x11E
312+#define REG_AUTO_CFG 0x11F
313+#define REG_AUTO_TX1 0x120
314+#define REG_AUTO_TX2 0x121
315+#define REG_AUTO_STATUS 0x122
316+
317+/* REG_FFILT_CFG */
318+#define ACCEPT_BEACON_FRAMES (1 << 0)
319+#define ACCEPT_DATA_FRAMES (1 << 1)
320+#define ACCEPT_ACK_FRAMES (1 << 2)
321+#define ACCEPT_MACCMD_FRAMES (1 << 3)
322+#define ACCEPT_RESERVED_FRAMES (1 << 4)
323+#define ACCEPT_ALL_ADDRESS (1 << 5)
324+
325+/* REG_AUTO_CFG */
326+#define AUTO_ACK_FRAMEPEND (1 << 0)
327+#define IS_PANCOORD (1 << 1)
328+#define RX_AUTO_ACK_EN (1 << 3)
329+#define CSMA_CA_RX_TURNAROUND (1 << 4)
330+
331+/* REG_AUTO_TX1 */
332+#define MAX_FRAME_RETRIES(x) ((x) & 0xF)
333+#define MAX_CCA_RETRIES(x) (((x) & 0x7) << 4)
334+
335+/* REG_AUTO_TX2 */
336+#define CSMA_MAX_BE(x) ((x) & 0xF)
337+#define CSMA_MIN_BE(x) (((x) & 0xF) << 4)
338+
339+#define CMD_SPI_NOP 0xFF /* No operation. Use for dummy writes */
340+#define CMD_SPI_PKT_WR 0x10 /* Write telegram to the Packet RAM starting from the TX packet base address pointer tx_packet_base */
341+#define CMD_SPI_PKT_RD 0x30 /* Read telegram from the Packet RAM starting from RX packet base address pointer rxpb.rx_packet_base */
342+#define CMD_SPI_MEM_WR(x) (0x18 + (x >> 8)) /* Write data to MCR or Packet RAM sequentially */
343+#define CMD_SPI_MEM_RD(x) (0x38 + (x >> 8)) /* Read data from MCR or Packet RAM sequentially */
344+#define CMD_SPI_MEMR_WR(x) (0x08 + (x >> 8)) /* Write data to MCR or Packet RAM as random block */
345+#define CMD_SPI_MEMR_RD(x) (0x28 + (x >> 8)) /* Read data from MCR or Packet RAM as random block */
346+#define CMD_SPI_PRAM_WR 0x1E /* Write data sequentially to current PRAM page selected */
347+#define CMD_RC_SLEEP 0xB1 /* Invoke transition of radio controller into SLEEP state */
348+#define CMD_RC_IDLE 0xB2 /* Invoke transition of radio controller into IDLE state */
349+#define CMD_RC_PHY_RDY 0xB3 /* Invoke transition of radio controller into PHY_RDY state */
350+#define CMD_RC_RX 0xB4 /* Invoke transition of radio controller into RX state */
351+#define CMD_RC_TX 0xB5 /* Invoke transition of radio controller into TX state */
352+#define CMD_RC_MEAS 0xB6 /* Invoke transition of radio controller into MEAS state */
353+#define CMD_RC_CCA 0xB7 /* Invoke Clear channel assessment */
354+#define CMD_RC_CSMACA 0xC1 /* initiates CSMA-CA channel access sequence and frame transmission */
355+
356+/* STATUS */
357+
358+#define STAT_SPI_READY (1 << 7)
359+#define STAT_IRQ_STATUS (1 << 6)
360+#define STAT_RC_READY (1 << 5)
361+#define STAT_CCA_RESULT (1 << 4)
362+#define RC_STATUS_IDLE 1
363+#define RC_STATUS_MEAS 2
364+#define RC_STATUS_PHY_RDY 3
365+#define RC_STATUS_RX 4
366+#define RC_STATUS_TX 5
367+#define RC_STATUS_MASK 0xF
368+
369+/* AUTO_STATUS */
370+
371+#define SUCCESS 0
372+#define SUCCESS_DATPEND 1
373+#define FAILURE_CSMACA 2
374+#define FAILURE_NOACK 3
375+#define AUTO_STATUS_MASK 0x3
376+
377+#define PRAM_PAGESIZE 256
378+
379+/* IRQ1 */
380+
381+#define IRQ_CCA_COMPLETE (1 << 0)
382+#define IRQ_SFD_RX (1 << 1)
383+#define IRQ_SFD_TX (1 << 2)
384+#define IRQ_RX_PKT_RCVD (1 << 3)
385+#define IRQ_TX_PKT_SENT (1 << 4)
386+#define IRQ_FRAME_VALID (1 << 5)
387+#define IRQ_ADDRESS_VALID (1 << 6)
388+#define IRQ_CSMA_CA (1 << 7)
389+
390+#define AUTO_TX_TURNAROUND (1 << 3)
391+#define ADDON_EN (1 << 4)
392+
393+struct adf7242_local {
394+ struct spi_device *spi;
395+ struct adf7242_platform_data *pdata;
396+ struct work_struct irqwork;
397+ struct completion tx_complete;
398+ struct ieee802154_dev *dev;
399+ struct mutex bmux;
400+ spinlock_t lock;
401+ unsigned irq_disabled:1; /* P: lock */
402+ unsigned is_tx:1; /* P: lock */
403+ unsigned mode;
404+ unsigned tx_irq;
405+ int tx_stat;
406+ u8 buf[3];
407+};
408+
409+static int adf7242_status(struct adf7242_local *lp, u8 *stat)
410+{
411+ int status;
412+ struct spi_message msg;
413+ u8 buf_tx[1], buf_rx[1];
414+
415+ struct spi_transfer xfer = {
416+ .len = 1,
417+ .tx_buf = buf_tx,
418+ .rx_buf = buf_rx,
419+ };
420+
421+ buf_tx[0] = CMD_SPI_NOP;
422+
423+ spi_message_init(&msg);
424+ spi_message_add_tail(&xfer, &msg);
425+
426+ mutex_lock(&lp->bmux);
427+ status = spi_sync(lp->spi, &msg);
428+ mutex_unlock(&lp->bmux);
429+
430+ *stat = buf_rx[0];
431+
432+ return status;
433+}
434+
435+static int adf7242_wait_ready(struct adf7242_local *lp)
436+{
437+ u8 stat;
438+ int cnt = 0;
439+
440+ DBG(2, "%s :Enter\n", __func__);
441+
442+ do {
443+ adf7242_status(lp, &stat);
444+ cnt++;
445+ } while (!(stat & STAT_RC_READY) && (cnt < MAX_POLL_LOOPS));
446+
447+ DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
448+
449+ return 0;
450+}
451+
452+static int adf7242_wait_status(struct adf7242_local *lp, int status)
453+{
454+ u8 stat;
455+ int cnt = 0;
456+
457+ DBG(2, "%s :Enter\n", __func__);
458+
459+ do {
460+ adf7242_status(lp, &stat);
461+ stat &= RC_STATUS_MASK;
462+ cnt++;
463+ } while ((stat != status) && (cnt < MAX_POLL_LOOPS));
464+
465+ DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
466+
467+ return 0;
468+}
469+
470+static int adf7242_write_fbuf(struct adf7242_local *lp, u8 *data, u8 len)
471+{
472+ u8 *buf = lp->buf;
473+ int status;
474+ struct spi_message msg;
475+ struct spi_transfer xfer_head = {
476+ .len = 2,
477+ .tx_buf = buf,
478+
479+ };
480+ struct spi_transfer xfer_buf = {
481+ .len = len,
482+ .tx_buf = data,
483+ };
484+
485+ DBG(2, "%s :Enter\n", __func__);
486+ adf7242_wait_ready(lp);
487+
488+ buf[0] = CMD_SPI_PKT_WR;
489+ buf[1] = len + 2;
490+
491+ spi_message_init(&msg);
492+ spi_message_add_tail(&xfer_head, &msg);
493+ spi_message_add_tail(&xfer_buf, &msg);
494+
495+ mutex_lock(&lp->bmux);
496+ status = spi_sync(lp->spi, &msg);
497+ mutex_unlock(&lp->bmux);
498+
499+ DBG(2, "%s :Exit\n", __func__);
500+ return status;
501+}
502+
503+static int adf7242_read_fbuf(struct adf7242_local *lp,
504+ u8 *data, u8 *len, u8 *lqi)
505+{
506+ u8 *buf = lp->buf;
507+ int status;
508+ struct spi_message msg;
509+ struct spi_transfer xfer_head = {
510+ .len = 3,
511+ .tx_buf = buf,
512+ .rx_buf = buf,
513+
514+ };
515+ struct spi_transfer xfer_buf = {
516+ .len = *len,
517+ .rx_buf = data,
518+ };
519+
520+ DBG(2, "%s :Enter\n", __func__);
521+ adf7242_wait_ready(lp);
522+
523+ mutex_lock(&lp->bmux);
524+ buf[0] = CMD_SPI_PKT_RD;
525+ buf[1] = CMD_SPI_NOP;
526+ buf[2] = 0; /* PHR */
527+
528+ spi_message_init(&msg);
529+ spi_message_add_tail(&xfer_head, &msg);
530+ spi_message_add_tail(&xfer_buf, &msg);
531+
532+ status = spi_sync(lp->spi, &msg);
533+
534+ if (!status) {
535+ *lqi = data[buf[2] - 1];
536+ *len = buf[2]; /* PHR */
537+ }
538+
539+ mutex_unlock(&lp->bmux);
540+ DBG(2, "%s :Exit\n", __func__);
541+ return status;
542+}
543+
544+static int adf7242_read_reg(struct adf7242_local *lp,
545+ u16 addr, u8 *data)
546+{
547+ int status;
548+ struct spi_message msg;
549+ u8 buf_tx[4], buf_rx[4];
550+
551+ struct spi_transfer xfer = {
552+ .len = 4,
553+ .tx_buf = buf_tx,
554+ .rx_buf = buf_rx,
555+ };
556+
557+ DBG(2, "%s :Enter\n", __func__);
558+ adf7242_wait_ready(lp);
559+
560+ mutex_lock(&lp->bmux);
561+ buf_tx[0] = CMD_SPI_MEM_RD(addr);
562+ buf_tx[1] = addr;
563+ buf_tx[2] = CMD_SPI_NOP;
564+ buf_tx[3] = CMD_SPI_NOP;
565+
566+ spi_message_init(&msg);
567+ spi_message_add_tail(&xfer, &msg);
568+
569+ status = spi_sync(lp->spi, &msg);
570+ if (msg.status)
571+ status = msg.status;
572+
573+ if (!status)
574+ *data = buf_rx[3];
575+
576+ mutex_unlock(&lp->bmux);
577+ DBG(2, "%s :Exit\n", __func__);
578+
579+ return status;
580+}
581+
582+static int adf7242_write_reg(struct adf7242_local *lp,
583+ u16 addr, u8 data)
584+{
585+ int status;
586+ struct spi_message msg;
587+ u8 buf_tx[4];
588+
589+ struct spi_transfer xfer = {
590+ .len = 3,
591+ .tx_buf = buf_tx,
592+ };
593+ DBG(2, "%s :Enter\n", __func__);
594+ adf7242_wait_ready(lp);
595+
596+ buf_tx[0] = CMD_SPI_MEM_WR(addr);
597+ buf_tx[1] = addr;
598+ buf_tx[2] = data;
599+
600+ spi_message_init(&msg);
601+ spi_message_add_tail(&xfer, &msg);
602+
603+ mutex_lock(&lp->bmux);
604+ status = spi_sync(lp->spi, &msg);
605+ mutex_unlock(&lp->bmux);
606+ DBG(2, "%s :Exit\n", __func__);
607+
608+ return status;
609+}
610+
611+static int adf7242_cmd(struct adf7242_local *lp, u8 cmd)
612+{
613+ int status;
614+ struct spi_message msg;
615+ u8 buf_tx[1];
616+
617+ struct spi_transfer xfer = {
618+ .len = 1,
619+ .tx_buf = buf_tx,
620+ };
621+
622+ DBG(2, "%s :Enter CMD=0x%X\n", __func__, cmd);
623+ adf7242_wait_ready(lp);
624+
625+ buf_tx[0] = cmd;
626+ spi_message_init(&msg);
627+ spi_message_add_tail(&xfer, &msg);
628+
629+ mutex_lock(&lp->bmux);
630+ status = spi_sync(lp->spi, &msg);
631+ mutex_unlock(&lp->bmux);
632+ DBG(2, "%s :Exit\n", __func__);
633+
634+ return status;
635+}
636+
637+static int adf7242_upload_firmware(struct adf7242_local *lp,
638+ u8 *data, u16 len)
639+{
640+ int status, i, page = 0;
641+ struct spi_message msg;
642+ struct spi_transfer xfer_buf = {};
643+ u8 buf[2];
644+
645+ struct spi_transfer xfer_head = {
646+ .len = 2,
647+ .tx_buf = buf,
648+ };
649+
650+ buf[0] = CMD_SPI_PRAM_WR;
651+ buf[1] = 0;
652+
653+ for (i = len; i >= 0 ; i -= PRAM_PAGESIZE) {
654+ adf7242_write_reg(lp, REG_PRAMPG, page);
655+
656+ xfer_buf.len = i >= PRAM_PAGESIZE ? PRAM_PAGESIZE : i,
657+ xfer_buf.tx_buf = &data[page * PRAM_PAGESIZE],
658+
659+ spi_message_init(&msg);
660+ spi_message_add_tail(&xfer_head, &msg);
661+ spi_message_add_tail(&xfer_buf, &msg);
662+
663+ mutex_lock(&lp->bmux);
664+ status = spi_sync(lp->spi, &msg);
665+ mutex_unlock(&lp->bmux);
666+ page++;
667+ }
668+
669+ return status;
670+}
671+
672+static int adf7242_ed(struct ieee802154_dev *dev, u8 *level)
673+{
674+ struct adf7242_local *lp = dev->priv;
675+ int ret;
676+
677+ DBG(2, "%s :Enter\n", __func__);
678+#if 0
679+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
680+ adf7242_cmd(lp, CMD_RC_CCA);
681+ adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
682+#else
683+ udelay(128);
684+#endif
685+ ret = adf7242_read_reg(lp, REG_RRB, level);
686+ adf7242_cmd(lp, CMD_RC_RX);
687+ DBG(2, "%s :Exit\n", __func__);
688+
689+ return ret;
690+}
691+
692+static int adf7242_start(struct ieee802154_dev *dev)
693+{
694+ struct adf7242_local *lp = dev->priv;
695+ int ret;
696+
697+ DBG(2, "%s :Enter\n", __func__);
698+ ret = adf7242_cmd(lp, CMD_RC_RX);
699+ DBG(2, "%s :Exit\n", __func__);
700+
701+ return ret;
702+}
703+
704+static void adf7242_stop(struct ieee802154_dev *dev)
705+{
706+ struct adf7242_local *lp = dev->priv;
707+
708+ DBG(2, "%s :Enter\n", __func__);
709+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
710+ DBG(2, "%s :Exit\n", __func__);
711+}
712+
713+static int adf7242_channel(struct ieee802154_dev *dev, int page, int channel)
714+{
715+ struct adf7242_local *lp = dev->priv;
716+ unsigned long freq;
717+
718+ DBG(2, "%s :Enter\n", __func__);
719+ DBG(1, "%s :Channel=%d\n", __func__, channel);
720+
721+ might_sleep();
722+
723+ BUG_ON(page != 0);
724+ BUG_ON(channel < 11);
725+ BUG_ON(channel > 26);
726+
727+ freq = (2405 + 5 * (channel - 11)) * 100;
728+
729+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
730+
731+ adf7242_write_reg(lp, REG_CH_FREQ0, freq);
732+ adf7242_write_reg(lp, REG_CH_FREQ1, freq >> 8);
733+ adf7242_write_reg(lp, REG_CH_FREQ2, freq >> 16);
734+
735+ adf7242_cmd(lp, CMD_RC_RX);
736+
737+ dev->phy->current_channel = channel;
738+ DBG(2, "%s :Exit\n", __func__);
739+
740+ return 0;
741+}
742+
743+static int adf7242_set_hw_addr_filt(struct ieee802154_dev *dev,
744+ struct ieee802154_hw_addr_filt *filt,
745+ unsigned long changed)
746+{
747+ struct adf7242_local *lp = dev->priv;
748+ u8 reg;
749+
750+ DBG(2, "%s :Enter\n", __func__);
751+ DBG(1, "%s :Changed=0x%lX\n", __func__, changed);
752+
753+ might_sleep();
754+
755+ if (changed & IEEE802515_IEEEADDR_CHANGED) {
756+ adf7242_write_reg(lp, REG_IEEE_ADDR_0, filt->ieee_addr[7]);
757+ adf7242_write_reg(lp, REG_IEEE_ADDR_1, filt->ieee_addr[6]);
758+ adf7242_write_reg(lp, REG_IEEE_ADDR_2, filt->ieee_addr[5]);
759+ adf7242_write_reg(lp, REG_IEEE_ADDR_3, filt->ieee_addr[4]);
760+ adf7242_write_reg(lp, REG_IEEE_ADDR_4, filt->ieee_addr[3]);
761+ adf7242_write_reg(lp, REG_IEEE_ADDR_5, filt->ieee_addr[2]);
762+ adf7242_write_reg(lp, REG_IEEE_ADDR_6, filt->ieee_addr[1]);
763+ adf7242_write_reg(lp, REG_IEEE_ADDR_7, filt->ieee_addr[0]);
764+ }
765+
766+ if (changed & IEEE802515_SADDR_CHANGED) {
767+ adf7242_write_reg(lp, REG_SHORT_ADDR_0, filt->short_addr);
768+ adf7242_write_reg(lp, REG_SHORT_ADDR_1, filt->short_addr >> 8);
769+ }
770+
771+ if (changed & IEEE802515_PANID_CHANGED) {
772+ adf7242_write_reg(lp, REG_PAN_ID0, filt->pan_id);
773+ adf7242_write_reg(lp, REG_PAN_ID1, filt->pan_id >> 8);
774+ }
775+
776+ if (changed & IEEE802515_PANC_CHANGED) {
777+ adf7242_read_reg(lp, REG_AUTO_CFG, &reg);
778+ if (filt->pan_coord)
779+ reg |= IS_PANCOORD;
780+ else
781+ reg &= ~IS_PANCOORD;
782+ adf7242_write_reg(lp, REG_AUTO_CFG, reg);
783+ }
784+
785+ DBG(2, "%s :Exit\n", __func__);
786+ return 0;
787+}
788+
789+static int adf7242_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
790+{
791+ struct adf7242_local *lp = dev->priv;
792+ int ret;
793+ unsigned long flags;
794+
795+ DBG(2, "%s :Enter\n", __func__);
796+
797+ spin_lock_irqsave(&lp->lock, flags);
798+ BUG_ON(lp->is_tx);
799+ lp->is_tx = 1;
800+ spin_unlock_irqrestore(&lp->lock, flags);
801+
802+ ret = adf7242_write_fbuf(lp, skb->data, skb->len);
803+ if (ret)
804+ goto err_rx;
805+
806+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
807+ ret = adf7242_cmd(lp, CMD_RC_PHY_RDY);
808+ ret |= adf7242_cmd(lp, CMD_RC_CSMACA);
809+ } else {
810+ ret = adf7242_cmd(lp, CMD_RC_TX);
811+ }
812+
813+ if (ret)
814+ goto err_rx;
815+
816+ ret = wait_for_completion_interruptible(&lp->tx_complete);
817+
818+ if (ret < 0)
819+ goto err_rx;
820+
821+ DBG(2, "%s :Exit\n", __func__);
822+ return ret;
823+
824+err_rx:
825+ spin_lock_irqsave(&lp->lock, flags);
826+ lp->is_tx = 0;
827+ spin_unlock_irqrestore(&lp->lock, flags);
828+ return ret;
829+}
830+
831+static int adf7242_rx(struct adf7242_local *lp)
832+{
833+ u8 len = 128;
834+ u8 lqi = 0;
835+ int ret;
836+ struct sk_buff *skb;
837+
838+ DBG(2, "%s :Enter\n", __func__);
839+
840+ skb = alloc_skb(len, GFP_KERNEL);
841+ if (!skb)
842+ return -ENOMEM;
843+
844+ ret = adf7242_read_fbuf(lp, skb_put(skb, len), &len, &lqi);
845+
846+ adf7242_cmd(lp, CMD_RC_RX);
847+
848+ skb_trim(skb, len - 2); /* We do not put RSSI/LQI or CRC into the frame */
849+
850+ if (len < 2) {
851+ kfree_skb(skb);
852+ return -EINVAL;
853+ }
854+
855+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
856+
857+ DBG(1, "%s: %d %d %x\n", __func__, ret, len, lqi);
858+ DBG(2, "%s :Exit\n", __func__);
859+
860+ return 0;
861+}
862+
863+static struct ieee802154_ops adf7242_ops = {
864+ .owner = THIS_MODULE,
865+ .xmit = adf7242_xmit,
866+ .ed = adf7242_ed,
867+ .set_channel = adf7242_channel,
868+ .set_hw_addr_filt = adf7242_set_hw_addr_filt,
869+ .start = adf7242_start,
870+ .stop = adf7242_stop,
871+};
872+
873+static void adf7242_irqwork(struct work_struct *work)
874+{
875+ struct adf7242_local *lp =
876+ container_of(work, struct adf7242_local, irqwork);
877+ u8 irq1, auto_stat = 0, stat = 0;
878+ int ret;
879+ unsigned long flags;
880+
881+ DBG(2, "%s :Enter\n", __func__);
882+
883+ ret = adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
884+
885+ DBG(1, "%s IRQ1 = %X:\n%s%s%s%s%s%s%s%s\n", __func__, irq1,
886+ irq1 & IRQ_CCA_COMPLETE ? "IRQ_CCA_COMPLETE\n" : "",
887+ irq1 & IRQ_SFD_RX ? "IRQ_SFD_RX\n" : "",
888+ irq1 & IRQ_SFD_TX ? "IRQ_SFD_TX\n" : "",
889+ irq1 & IRQ_RX_PKT_RCVD ? "IRQ_RX_PKT_RCVD\n" : "",
890+ irq1 & IRQ_TX_PKT_SENT ? "IRQ_TX_PKT_SENT\n" : "",
891+ irq1 & IRQ_CSMA_CA ? "IRQ_CSMA_CA\n" : "",
892+ irq1 & IRQ_FRAME_VALID ? "IRQ_FRAME_VALID\n" : "",
893+ irq1 & IRQ_ADDRESS_VALID ? "IRQ_ADDRESS_VALID\n" : "");
894+
895+ adf7242_status(lp, &stat);
896+
897+ DBG(1, "%s STATUS = %X:\n%s\n%s%s%s%s%s\n", __func__, stat,
898+ stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
899+ (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" : "",
900+ (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" : "",
901+ (stat & 0xf) == RC_STATUS_PHY_RDY ? "RC_STATUS_PHY_RDY" : "",
902+ (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
903+ (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
904+
905+ adf7242_write_reg(lp, REG_IRQ1_SRC1, irq1);
906+
907+ if (irq1 & IRQ_RX_PKT_RCVD) {
908+
909+ /* Wait until ACK is processed */
910+ if ((lp->mode & ADF_IEEE802154_HW_AACK) &&
911+ ((stat & RC_STATUS_MASK) != RC_STATUS_PHY_RDY))
912+ adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
913+
914+ adf7242_rx(lp);
915+ }
916+
917+ if (irq1 & lp->tx_irq) {
918+
919+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
920+ adf7242_read_reg(lp, REG_AUTO_STATUS, &auto_stat);
921+ auto_stat &= AUTO_STATUS_MASK;
922+
923+ DBG(1, "%s AUTO_STATUS = %X:\n%s%s%s%s\n",
924+ __func__, auto_stat,
925+ auto_stat == SUCCESS ? "SUCCESS" : "",
926+ auto_stat == SUCCESS_DATPEND ? "SUCCESS_DATPEND" : "",
927+ auto_stat == FAILURE_CSMACA ? "FAILURE_CSMACA" : "",
928+ auto_stat == FAILURE_NOACK ? "FAILURE_NOACK" : "");
929+
930+ /* save CSMA-CA completion status */
931+ lp->tx_stat = auto_stat;
932+ }
933+ spin_lock_irqsave(&lp->lock, flags);
934+ if (lp->is_tx) {
935+ lp->is_tx = 0;
936+ complete(&lp->tx_complete);
937+ }
938+ spin_unlock_irqrestore(&lp->lock, flags);
939+
940+ /* in case we just received a frame we are already in PHY_RX */
941+
942+ if (!(irq1 & IRQ_RX_PKT_RCVD))
943+ adf7242_cmd(lp, CMD_RC_RX);
944+ }
945+
946+ spin_lock_irqsave(&lp->lock, flags);
947+ if (lp->irq_disabled) {
948+ lp->irq_disabled = 0;
949+ enable_irq(lp->spi->irq);
950+ }
951+ spin_unlock_irqrestore(&lp->lock, flags);
952+
953+ DBG(2, "%s :Exit\n", __func__);
954+}
955+
956+static irqreturn_t adf7242_isr(int irq, void *data)
957+{
958+ struct adf7242_local *lp = data;
959+
960+ DBG(2, "%s :Enter\n", __func__);
961+
962+ spin_lock(&lp->lock);
963+ if (!lp->irq_disabled) {
964+ disable_irq_nosync(irq);
965+ lp->irq_disabled = 1;
966+ }
967+ spin_unlock(&lp->lock);
968+
969+ schedule_work(&lp->irqwork);
970+
971+ DBG(2, "%s :Exit\n", __func__);
972+
973+ return IRQ_HANDLED;
974+}
975+
976+
977+static int adf7242_hw_init(struct adf7242_local *lp)
978+{
979+ int ret;
980+ const struct firmware *fw;
981+
982+ DBG(2, "%s :Enter\n", __func__);
983+
984+ adf7242_cmd(lp, CMD_RC_IDLE);
985+
986+ if (lp->mode) {
987+ /* get ADF7242 addon firmware
988+ * build this driver as module
989+ * and place under /lib/firmware/adf7242_firmware.bin
990+ */
991+ ret = request_firmware(&fw, FIRMWARE, &lp->spi->dev);
992+ if (ret) {
993+ dev_err(&lp->spi->dev,
994+ "request_firmware() failed with %i\n", ret);
995+ return ret;
996+ }
997+
998+ adf7242_upload_firmware(lp, (u8 *) fw->data, fw->size);
999+ release_firmware(fw);
1000+
1001+ adf7242_write_reg(lp, REG_FFILT_CFG,
1002+ ACCEPT_BEACON_FRAMES |
1003+ ACCEPT_DATA_FRAMES |
1004+ ACCEPT_ACK_FRAMES |
1005+ ACCEPT_MACCMD_FRAMES |
1006+ (lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE ?
1007+ ACCEPT_ALL_ADDRESS : 0) |
1008+ ACCEPT_RESERVED_FRAMES);
1009+
1010+ adf7242_write_reg(lp, REG_AUTO_TX1,
1011+ MAX_FRAME_RETRIES(lp->pdata->max_frame_retries) |
1012+ MAX_CCA_RETRIES(lp->pdata->max_cca_retries));
1013+
1014+ adf7242_write_reg(lp, REG_AUTO_TX2,
1015+ CSMA_MAX_BE(lp->pdata->max_csma_be) |
1016+ CSMA_MIN_BE(lp->pdata->min_csma_be));
1017+
1018+ adf7242_write_reg(lp, REG_AUTO_CFG,
1019+ (lp->mode & ADF_IEEE802154_HW_AACK ?
1020+ RX_AUTO_ACK_EN : 0));
1021+ }
1022+
1023+ adf7242_write_reg(lp, REG_PKT_CFG, lp->mode ? ADDON_EN : 0);
1024+
1025+ adf7242_write_reg(lp, REG_EXTPA_MSC, 0xF1);
1026+ adf7242_write_reg(lp, REG_RXFE_CFG, 0x1D);
1027+ adf7242_write_reg(lp, REG_IRQ1_EN0, 0);
1028+
1029+ adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | lp->tx_irq);
1030+
1031+ adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
1032+ adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF);
1033+
1034+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
1035+
1036+ DBG(2, "%s :Exit\n", __func__);
1037+
1038+ return 0;
1039+}
1040+
1041+static int adf7242_suspend(struct spi_device *spi, pm_message_t message)
1042+{
1043+ return 0;
1044+}
1045+
1046+static int adf7242_resume(struct spi_device *spi)
1047+{
1048+ return 0;
1049+}
1050+
1051+static ssize_t adf7242_show(struct device *dev,
1052+ struct device_attribute *devattr,
1053+ char *buf)
1054+{
1055+ struct adf7242_local *lp = dev_get_drvdata(dev);
1056+ u8 stat;
1057+
1058+ adf7242_status(lp, &stat);
1059+
1060+ return sprintf(buf, "STATUS = %X:\n%s\n%s%s%s%s%s\n", stat,
1061+ stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
1062+ (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" : "",
1063+ (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" : "",
1064+ (stat & 0xf) == RC_STATUS_PHY_RDY ? "RC_STATUS_PHY_RDY" : "",
1065+ (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
1066+ (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
1067+
1068+}
1069+static DEVICE_ATTR(status, 0664, adf7242_show, NULL);
1070+
1071+static struct attribute *adf7242_attributes[] = {
1072+ &dev_attr_status.attr,
1073+ NULL
1074+};
1075+
1076+static const struct attribute_group adf7242_attr_group = {
1077+ .attrs = adf7242_attributes,
1078+};
1079+
1080+static int __devinit adf7242_probe(struct spi_device *spi)
1081+{
1082+ struct adf7242_platform_data *pdata = spi->dev.platform_data;
1083+ struct ieee802154_dev *dev;
1084+ struct adf7242_local *lp;
1085+ int ret;
1086+
1087+ if (!spi->irq) {
1088+ dev_err(&spi->dev, "no IRQ specified\n");
1089+ return -EINVAL;
1090+ }
1091+
1092+ if (!pdata) {
1093+ dev_err(&spi->dev, "no platform data?\n");
1094+ return -ENODEV;
1095+ }
1096+
1097+ dev = ieee802154_alloc_device(sizeof(*lp), &adf7242_ops);
1098+ if (!dev)
1099+ return -ENOMEM;
1100+
1101+ lp = dev->priv;
1102+ lp->dev = dev;
1103+ lp->spi = spi;
1104+ lp->pdata = pdata;
1105+ lp->mode = pdata->mode;
1106+
1107+ dev->priv = lp;
1108+ dev->parent = &spi->dev;
1109+ dev->extra_tx_headroom = 0;
1110+ /* We do support only 2.4 Ghz */
1111+
1112+ dev->phy->channels_supported[0] = 0x7FFF800;
1113+
1114+ if (!lp->mode) {
1115+ adf7242_ops.set_hw_addr_filt = NULL;
1116+ lp->tx_irq = IRQ_TX_PKT_SENT;
1117+ } else {
1118+ if ((lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE) &&
1119+ (lp->mode & ADF_IEEE802154_HW_AACK))
1120+ lp->mode &= ~ADF_IEEE802154_HW_AACK;
1121+
1122+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA)
1123+ lp->tx_irq = IRQ_CSMA_CA;
1124+ else
1125+ lp->tx_irq = IRQ_TX_PKT_SENT;
1126+ }
1127+
1128+ dev->flags = IEEE802154_HW_OMIT_CKSUM |
1129+ (lp->mode & ADF_IEEE802154_HW_AACK ?
1130+ IEEE802154_HW_AACK : 0);
1131+
1132+ mutex_init(&lp->bmux);
1133+ INIT_WORK(&lp->irqwork, adf7242_irqwork);
1134+ spin_lock_init(&lp->lock);
1135+ init_completion(&lp->tx_complete);
1136+
1137+ spi_set_drvdata(spi, lp);
1138+
1139+ ret = adf7242_hw_init(lp);
1140+ if (ret)
1141+ goto err_hw_init;
1142+
1143+ ret = request_irq(spi->irq, adf7242_isr, IRQF_TRIGGER_HIGH,
1144+ dev_name(&spi->dev), lp);
1145+ if (ret)
1146+ goto err_hw_init;
1147+
1148+ ret = ieee802154_register_device(lp->dev);
1149+ if (ret)
1150+ goto err_irq;
1151+
1152+ dev_set_drvdata(&spi->dev, lp);
1153+
1154+ ret = sysfs_create_group(&spi->dev.kobj, &adf7242_attr_group);
1155+ if (ret)
1156+ goto out;
1157+
1158+ dev_info(&spi->dev, "mac802154 IRQ-%d registered\n", spi->irq);
1159+
1160+ return ret;
1161+
1162+out:
1163+ ieee802154_unregister_device(lp->dev);
1164+err_irq:
1165+ free_irq(spi->irq, lp);
1166+ flush_work(&lp->irqwork);
1167+err_hw_init:
1168+ spi_set_drvdata(spi, NULL);
1169+ mutex_destroy(&lp->bmux);
1170+ ieee802154_free_device(lp->dev);
1171+ return ret;
1172+}
1173+
1174+static int __devexit adf7242_remove(struct spi_device *spi)
1175+{
1176+ struct adf7242_local *lp = spi_get_drvdata(spi);
1177+
1178+ ieee802154_unregister_device(lp->dev);
1179+ free_irq(spi->irq, lp);
1180+ flush_work(&lp->irqwork);
1181+ spi_set_drvdata(spi, NULL);
1182+ mutex_destroy(&lp->bmux);
1183+ ieee802154_free_device(lp->dev);
1184+
1185+ return 0;
1186+}
1187+
1188+static struct spi_driver adf7242_driver = {
1189+ .driver = {
1190+ .name = "adf7242",
1191+ .owner = THIS_MODULE,
1192+ },
1193+ .probe = adf7242_probe,
1194+ .remove = __devexit_p(adf7242_remove),
1195+ .suspend = adf7242_suspend,
1196+ .resume = adf7242_resume,
1197+};
1198+
1199+static int __init adf7242_init(void)
1200+{
1201+ return spi_register_driver(&adf7242_driver);
1202+}
1203+module_init(adf7242_init);
1204+
1205+static void __exit adf7242_exit(void)
1206+{
1207+ spi_unregister_driver(&adf7242_driver);
1208+}
1209+module_exit(adf7242_exit);
1210+
1211+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
1212+MODULE_DESCRIPTION("ADF7242 Transceiver Driver");
1213+MODULE_LICENSE("GPL");
1214diff --git a/drivers/ieee802154/at86rf230.c b/drivers/ieee802154/at86rf230.c
1215new file mode 100644
1216index 0000000..8da82cf
1217--- /dev/null
1218@@ -0,0 +1,872 @@
1219+/*
1220+ * AT86RF230/RF231 driver
1221+ *
1222+ * Copyright (C) 2009 Siemens AG
1223+ *
1224+ * This program is free software; you can redistribute it and/or modify
1225+ * it under the terms of the GNU General Public License version 2
1226+ * as published by the Free Software Foundation.
1227+ *
1228+ * This program is distributed in the hope that it will be useful,
1229+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1230+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1231+ * GNU General Public License for more details.
1232+ *
1233+ * You should have received a copy of the GNU General Public License along
1234+ * with this program; if not, write to the Free Software Foundation, Inc.,
1235+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1236+ *
1237+ * Written by:
1238+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
1239+ */
1240+#include <linux/kernel.h>
1241+#include <linux/module.h>
1242+#include <linux/interrupt.h>
1243+#include <linux/gpio.h>
1244+#include <linux/delay.h>
1245+#include <linux/mutex.h>
1246+#include <linux/workqueue.h>
1247+#include <linux/spi/spi.h>
1248+#include <linux/spi/at86rf230.h>
1249+
1250+#ifdef CONFIG_OF
1251+#include <linux/of.h>
1252+#include <linux/of_gpio.h>
1253+#endif
1254+
1255+#include <net/mac802154.h>
1256+#include <net/wpan-phy.h>
1257+
1258+#include "at86rf230.h"
1259+
1260+
1261+struct at86rf230_local {
1262+ struct spi_device *spi;
1263+ int rstn, slp_tr, dig2;
1264+ void (*reset)(void *reset_data);
1265+ void *reset_data;
1266+
1267+ u8 part;
1268+ u8 vers;
1269+
1270+ u8 buf[2];
1271+ struct mutex bmux;
1272+
1273+ struct work_struct irqwork;
1274+ struct completion tx_complete;
1275+
1276+ struct ieee802154_dev *dev;
1277+
1278+ volatile unsigned is_tx:1;
1279+};
1280+
1281+
1282+static int
1283+__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
1284+{
1285+ u8 *buf = lp->buf;
1286+ int status;
1287+ struct spi_message msg;
1288+ struct spi_transfer xfer = {
1289+ .len = 2,
1290+ .tx_buf = buf,
1291+ };
1292+
1293+ buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
1294+ buf[1] = data;
1295+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1296+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1297+ spi_message_init(&msg);
1298+ spi_message_add_tail(&xfer, &msg);
1299+
1300+ status = spi_sync(lp->spi, &msg);
1301+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1302+ if (msg.status)
1303+ status = msg.status;
1304+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1305+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1306+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1307+
1308+ return status;
1309+}
1310+
1311+static int
1312+__at86rf230_read_subreg(struct at86rf230_local *lp,
1313+ u8 addr, u8 mask, int shift, u8 *data)
1314+{
1315+ u8 *buf = lp->buf;
1316+ int status;
1317+ struct spi_message msg;
1318+ struct spi_transfer xfer = {
1319+ .len = 2,
1320+ .tx_buf = buf,
1321+ .rx_buf = buf,
1322+ };
1323+
1324+ buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
1325+ buf[1] = 0xff;
1326+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1327+ spi_message_init(&msg);
1328+ spi_message_add_tail(&xfer, &msg);
1329+
1330+ status = spi_sync(lp->spi, &msg);
1331+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1332+ if (msg.status)
1333+ status = msg.status;
1334+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1335+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1336+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1337+
1338+ if (status == 0)
1339+ *data = buf[1];
1340+
1341+ return status;
1342+}
1343+
1344+static int
1345+at86rf230_read_subreg(struct at86rf230_local *lp,
1346+ u8 addr, u8 mask, int shift, u8 *data)
1347+{
1348+ int status;
1349+
1350+ mutex_lock(&lp->bmux);
1351+ status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
1352+ mutex_unlock(&lp->bmux);
1353+
1354+ return status;
1355+}
1356+
1357+static int
1358+at86rf230_write_subreg(struct at86rf230_local *lp,
1359+ u8 addr, u8 mask, int shift, u8 data)
1360+{
1361+ int status;
1362+ u8 val;
1363+
1364+ mutex_lock(&lp->bmux);
1365+ status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
1366+ if (status)
1367+ goto out;
1368+
1369+ val &= ~mask;
1370+ val |= (data << shift) & mask;
1371+
1372+ status = __at86rf230_write(lp, addr, val);
1373+out:
1374+ mutex_unlock(&lp->bmux);
1375+
1376+ return status;
1377+}
1378+
1379+static int
1380+at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
1381+{
1382+ u8 *buf = lp->buf;
1383+ int status;
1384+ struct spi_message msg;
1385+ struct spi_transfer xfer_head = {
1386+ .len = 2,
1387+ .tx_buf = buf,
1388+
1389+ };
1390+ struct spi_transfer xfer_buf = {
1391+ .len = len,
1392+ .tx_buf = data,
1393+ };
1394+
1395+ mutex_lock(&lp->bmux);
1396+ buf[0] = CMD_WRITE | CMD_FB;
1397+ buf[1] = len + 2; /* 2 bytes for CRC that isn't written */
1398+
1399+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1400+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1401+
1402+ spi_message_init(&msg);
1403+ spi_message_add_tail(&xfer_head, &msg);
1404+ spi_message_add_tail(&xfer_buf, &msg);
1405+
1406+ status = spi_sync(lp->spi, &msg);
1407+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1408+ if (msg.status)
1409+ status = msg.status;
1410+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1411+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1412+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1413+
1414+ mutex_unlock(&lp->bmux);
1415+ return status;
1416+}
1417+
1418+static int
1419+at86rf230_read_fbuf(struct at86rf230_local *lp, u8 *data, u8 *len, u8 *lqi)
1420+{
1421+ u8 *buf = lp->buf;
1422+ int status;
1423+ struct spi_message msg;
1424+ struct spi_transfer xfer_head = {
1425+ .len = 2,
1426+ .tx_buf = buf,
1427+ .rx_buf = buf,
1428+ };
1429+ struct spi_transfer xfer_head1 = {
1430+ .len = 2,
1431+ .tx_buf = buf,
1432+ .rx_buf = buf,
1433+ };
1434+ struct spi_transfer xfer_buf = {
1435+ .len = 0,
1436+ .rx_buf = data,
1437+ };
1438+
1439+ mutex_lock(&lp->bmux);
1440+
1441+ buf[0] = CMD_FB;
1442+ buf[1] = 0x00;
1443+
1444+ spi_message_init(&msg);
1445+ spi_message_add_tail(&xfer_head, &msg);
1446+
1447+ status = spi_sync(lp->spi, &msg);
1448+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1449+
1450+ if (buf[1] & 0x80) {
1451+ dev_err(&lp->spi->dev, "invalid PHR 0x%02x\n", buf[1]);
1452+ status = -EIO;
1453+ goto fail;
1454+ }
1455+ if (buf[1] >= *len) {
1456+ dev_err(&lp->spi->dev, "PHR 0x%02x >= buffer %d bytes\n",
1457+ buf[1], *len);
1458+ status = -EMSGSIZE;
1459+ goto fail;
1460+ }
1461+ xfer_buf.len = *(buf + 1) + 1;
1462+ *len = buf[1];
1463+
1464+ buf[0] = CMD_FB;
1465+ buf[1] = 0x00;
1466+
1467+ spi_message_init(&msg);
1468+ spi_message_add_tail(&xfer_head1, &msg);
1469+ spi_message_add_tail(&xfer_buf, &msg);
1470+
1471+ status = spi_sync(lp->spi, &msg);
1472+
1473+ if (msg.status)
1474+ status = msg.status;
1475+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1476+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1477+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1478+
1479+ if (!status) {
1480+ if (lqi && *len > lp->buf[1])
1481+ *lqi = data[lp->buf[1]];
1482+ }
1483+
1484+fail:
1485+ mutex_unlock(&lp->bmux);
1486+
1487+ return status;
1488+}
1489+
1490+static int
1491+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
1492+{
1493+ pr_debug("%s\n", __func__);
1494+ might_sleep();
1495+ BUG_ON(!level);
1496+ *level = 0xbe;
1497+ return 0;
1498+}
1499+
1500+static int
1501+at86rf230_state(struct ieee802154_dev *dev, int state)
1502+{
1503+ struct at86rf230_local *lp = dev->priv;
1504+ int rc;
1505+ u8 val;
1506+ u8 desired_status;
1507+
1508+ pr_debug("%s %d\n", __func__/*, priv->cur_state*/, state);
1509+ might_sleep();
1510+
1511+ if (state == STATE_FORCE_TX_ON)
1512+ desired_status = STATE_TX_ON;
1513+ else if (state == STATE_FORCE_TRX_OFF)
1514+ desired_status = STATE_TRX_OFF;
1515+ else
1516+ desired_status = state;
1517+
1518+ do {
1519+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
1520+ if (rc)
1521+ goto err;
1522+ pr_debug("%s val1 = %x\n", __func__, val);
1523+ } while (val == STATE_TRANSITION_IN_PROGRESS);
1524+
1525+ if (val == desired_status)
1526+ return 0;
1527+
1528+ /* state is equal to phy states */
1529+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
1530+ if (rc)
1531+ goto err;
1532+
1533+ do {
1534+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
1535+ if (rc)
1536+ goto err;
1537+ pr_debug("%s val2 = %x\n", __func__, val);
1538+ } while (val == STATE_TRANSITION_IN_PROGRESS);
1539+
1540+
1541+ if (val == desired_status)
1542+ return 0;
1543+ if (state == STATE_RX_ON && val == STATE_BUSY_RX)
1544+ return 0;
1545+
1546+ pr_err("%s unexpected state change: %d, asked for %d\n", __func__,
1547+ val, state);
1548+ return -EBUSY;
1549+
1550+err:
1551+ pr_err("%s error: %d\n", __func__, rc);
1552+ return rc;
1553+}
1554+
1555+static int
1556+at86rf230_start(struct ieee802154_dev *dev)
1557+{
1558+ struct at86rf230_local *lp = dev->priv;
1559+ u8 rc;
1560+
1561+ rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
1562+ if (rc)
1563+ return rc;
1564+ return at86rf230_state(dev, STATE_RX_ON);
1565+}
1566+
1567+static void
1568+at86rf230_stop(struct ieee802154_dev *dev)
1569+{
1570+ at86rf230_state(dev, STATE_FORCE_TRX_OFF);
1571+}
1572+
1573+static int
1574+at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
1575+{
1576+ struct at86rf230_local *lp = dev->priv;
1577+ int rc;
1578+
1579+ pr_debug("%s %d\n", __func__, channel);
1580+ might_sleep();
1581+
1582+ BUG_ON(page != 0);
1583+ BUG_ON(channel < 11);
1584+ BUG_ON(channel > 26);
1585+
1586+ rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel);
1587+ msleep(1); /* Wait for PLL */
1588+ dev->phy->current_channel = channel;
1589+
1590+ return 0;
1591+}
1592+
1593+/* FIXME:
1594+ * This function currently is a mess. It uses flush_work to guard
1595+ * against concurrent irqwork, etc. One has to use mutexes intead. */
1596+static int
1597+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
1598+{
1599+ struct at86rf230_local *lp = dev->priv;
1600+ int rc;
1601+
1602+ pr_debug("%s\n", __func__);
1603+
1604+ might_sleep();
1605+
1606+ BUG_ON(lp->is_tx);
1607+ INIT_COMPLETION(lp->tx_complete);
1608+
1609+ rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
1610+ if (rc)
1611+ goto err;
1612+
1613+ synchronize_irq(lp->spi->irq);
1614+ flush_work(&lp->irqwork);
1615+
1616+ lp->is_tx = 1;
1617+
1618+ rc = at86rf230_write_fbuf(lp, skb->data, skb->len);
1619+ if (rc)
1620+ goto err_rx;
1621+
1622+ if (gpio_is_valid(lp->slp_tr)) {
1623+ gpio_set_value(lp->slp_tr, 1);
1624+ udelay(80); /* > 62.5 */
1625+ gpio_set_value(lp->slp_tr, 0);
1626+ } else {
1627+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
1628+ if (rc)
1629+ goto err_rx;
1630+ }
1631+
1632+ /* FIXME: the logic is really strange here. Datasheet doesn't
1633+ * provide us enough info about behaviour in such cases.
1634+ * Basically either we were interrupted here, or we have lost
1635+ * the interrupt. Most probably this should be changed to
1636+ * wait_for_completion_timeout() and handle it's results
1637+ */
1638+ rc = wait_for_completion_interruptible(&lp->tx_complete);
1639+ if (rc < 0)
1640+ goto err_state;
1641+
1642+ lp->is_tx = 0;
1643+
1644+ rc = at86rf230_start(dev);
1645+ return rc;
1646+
1647+err_state:
1648+ /* try to recover from possibly problematic state */
1649+ at86rf230_state(dev, STATE_FORCE_TX_ON);
1650+ synchronize_irq(lp->spi->irq);
1651+ flush_work(&lp->irqwork);
1652+ lp->is_tx = 0;
1653+err_rx:
1654+ at86rf230_start(dev);
1655+err:
1656+ if (rc)
1657+ pr_err("%s error: %d\n", __func__, rc);
1658+
1659+ return rc;
1660+}
1661+
1662+static int at86rf230_rx(struct at86rf230_local *lp)
1663+{
1664+ u8 len = 128, lqi = 0;
1665+ int rc, rc2;
1666+ struct sk_buff *skb;
1667+
1668+ skb = alloc_skb(len, GFP_KERNEL);
1669+ if (!skb)
1670+ return -ENOMEM;
1671+
1672+ /* FIXME: process return status */
1673+ rc = at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 1);
1674+ rc2 = at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi);
1675+ rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
1676+ rc = at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 0);
1677+ if (rc2 < 0)
1678+ goto err_fbuf;
1679+
1680+ if (len < 2)
1681+ goto err;
1682+
1683+ skb_trim(skb, len-2); /* We do not put CRC into the frame */
1684+
1685+
1686+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
1687+
1688+ dev_dbg(&lp->spi->dev, "READ_FBUF: %d %d %x\n", rc, len, lqi);
1689+
1690+ return 0;
1691+err:
1692+ pr_debug("%s: received frame is too small\n", __func__);
1693+
1694+err_fbuf:
1695+ kfree_skb(skb);
1696+ return -EINVAL;
1697+}
1698+
1699+static struct ieee802154_ops at86rf230_ops = {
1700+ .owner = THIS_MODULE,
1701+ .xmit = at86rf230_xmit,
1702+ .ed = at86rf230_ed,
1703+ .set_channel = at86rf230_channel,
1704+ .start = at86rf230_start,
1705+ .stop = at86rf230_stop,
1706+};
1707+
1708+static void at86rf230_irqwork(struct work_struct *work)
1709+{
1710+ struct at86rf230_local *lp =
1711+ container_of(work, struct at86rf230_local, irqwork);
1712+ u8 status = 0, val;
1713+ int rc;
1714+
1715+ dev_dbg(&lp->spi->dev, "IRQ Worker\n");
1716+
1717+ do {
1718+ rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
1719+ status |= val;
1720+ dev_dbg(&lp->spi->dev, "IRQ Status: %02x\n", status);
1721+
1722+ status &= ~IRQ_PLL_LOCK; /* ignore */
1723+ status &= ~IRQ_RX_START; /* ignore */
1724+ status &= ~IRQ_AMI; /* ignore */
1725+ status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/
1726+
1727+ if (status & IRQ_TRX_END) {
1728+ status &= ~IRQ_TRX_END;
1729+ if (lp->is_tx)
1730+ complete(&lp->tx_complete);
1731+ else
1732+ at86rf230_rx(lp);
1733+ }
1734+
1735+ } while (status != 0);
1736+
1737+ enable_irq(lp->spi->irq);
1738+}
1739+
1740+static irqreturn_t at86rf230_isr(int irq, void *data)
1741+{
1742+ struct at86rf230_local *lp = data;
1743+
1744+ dev_dbg(&lp->spi->dev, "IRQ!\n");
1745+
1746+ disable_irq_nosync(irq);
1747+ schedule_work(&lp->irqwork);
1748+
1749+ return IRQ_HANDLED;
1750+}
1751+
1752+
1753+static int at86rf230_hw_init(struct at86rf230_local *lp)
1754+{
1755+ u8 status;
1756+ int rc;
1757+
1758+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1759+ if (rc)
1760+ return rc;
1761+
1762+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1763+ if (status == STATE_P_ON) {
1764+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF);
1765+ if (rc)
1766+ return rc;
1767+ msleep(1);
1768+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1769+ if (rc)
1770+ return rc;
1771+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1772+ }
1773+
1774+ rc = at86rf230_write_subreg(lp, SR_IRQ_MASK,
1775+ /*IRQ_TRX_UR | IRQ_CCA_ED | IRQ_TRX_END | IRQ_PLL_UNL | IRQ_PLL_LOCK*/ 0xff);
1776+ if (rc)
1777+ return rc;
1778+
1779+ /* CLKM changes are applied immediately */
1780+ rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
1781+ if (rc)
1782+ return rc;
1783+
1784+ /* Turn CLKM Off */
1785+ rc = at86rf230_write_subreg(lp, SR_CLKM_CTRL, 0x00);
1786+ if (rc)
1787+ return rc;
1788+
1789+ msleep(100);
1790+
1791+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
1792+ if (rc)
1793+ return rc;
1794+ msleep(1);
1795+
1796+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1797+ if (rc)
1798+ return rc;
1799+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1800+
1801+ rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
1802+ if (rc)
1803+ return rc;
1804+ if (!status) {
1805+ dev_err(&lp->spi->dev, "DVDD error\n");
1806+ return -EINVAL;
1807+ }
1808+
1809+ rc = at86rf230_read_subreg(lp, SR_AVDD_OK, &status);
1810+ if (rc)
1811+ return rc;
1812+ if (!status) {
1813+ dev_err(&lp->spi->dev, "AVDD error\n");
1814+ return -EINVAL;
1815+ }
1816+
1817+ return 0;
1818+}
1819+
1820+static int at86rf230_suspend(struct spi_device *spi, pm_message_t message)
1821+{
1822+ return 0;
1823+}
1824+
1825+static int at86rf230_resume(struct spi_device *spi)
1826+{
1827+ return 0;
1828+}
1829+
1830+#ifdef CONFIG_OF
1831+static int at86rf230_fill_data(struct spi_device *spi)
1832+{
1833+ struct device_node *np = spi->dev.of_node;
1834+ struct at86rf230_local *lp = spi_get_drvdata(spi);
1835+ struct at86rf230_platform_data *pdata = spi->dev.platform_data;
1836+ enum of_gpio_flags gpio_flags;
1837+
1838+ if (pdata) {
1839+ lp->rstn = pdata->rstn;
1840+ lp->slp_tr = pdata->slp_tr;
1841+ lp->dig2 = pdata->dig2;
1842+ lp->reset = pdata->reset;
1843+ lp->reset_data = pdata->reset_data;
1844+
1845+ return 0;
1846+ }
1847+
1848+ if (!np) {
1849+ dev_err(&spi->dev, "no platform_data and no node data\n");
1850+ return -EINVAL;
1851+ }
1852+
1853+ lp->rstn = of_get_gpio_flags(np, 0, &gpio_flags);
1854+ if (!gpio_is_valid(lp->rstn)) {
1855+ dev_err(&spi->dev, "no RSTN GPIO!\n");
1856+ return -EINVAL;
1857+ }
1858+
1859+ lp->slp_tr = of_get_gpio_flags(np, 1, &gpio_flags);
1860+ lp->dig2 = of_get_gpio_flags(np, 2, &gpio_flags);
1861+
1862+ lp->reset = NULL;
1863+
1864+ return 0;
1865+}
1866+#else
1867+static int at86rf230_fill_data(struct spi_device *spi)
1868+{
1869+ struct at86rf230_local *lp = spi_get_drvdata(spi);
1870+ struct at86rf230_platform_data *pdata = spi->dev.platform_data;
1871+
1872+ if (!pdata) {
1873+ dev_err(&spi->dev, "no platform_data\n");
1874+ return -EINVAL;
1875+ }
1876+
1877+ lp->rstn = pdata->rstn;
1878+ lp->slp_tr = pdata->slp_tr;
1879+ lp->dig2 = pdata->dig2;
1880+ lp->reset = pdata->reset;
1881+ lp->reset_data = pdata->reset_data;
1882+
1883+ return 0;
1884+}
1885+#endif
1886+
1887+static int __devinit at86rf230_probe(struct spi_device *spi)
1888+{
1889+ struct ieee802154_dev *dev;
1890+ struct at86rf230_local *lp;
1891+ u8 man_id_0, man_id_1;
1892+ int rc;
1893+ const char *chip;
1894+ int supported = 0;
1895+
1896+ if (spi->irq < 0) {
1897+ dev_err(&spi->dev, "no IRQ specified\n");
1898+ return -EINVAL;
1899+ }
1900+
1901+ dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
1902+ if (!dev)
1903+ return -ENOMEM;
1904+
1905+ lp = dev->priv;
1906+ lp->dev = dev;
1907+
1908+ lp->spi = spi;
1909+
1910+ dev->priv = lp;
1911+ dev->parent = &spi->dev;
1912+ dev->extra_tx_headroom = 0;
1913+ /* We do support only 2.4 Ghz */
1914+ dev->phy->channels_supported[0] = 0x7FFF800;
1915+ dev->flags = IEEE802154_HW_OMIT_CKSUM;
1916+
1917+ mutex_init(&lp->bmux);
1918+ INIT_WORK(&lp->irqwork, at86rf230_irqwork);
1919+ init_completion(&lp->tx_complete);
1920+
1921+ spi_set_drvdata(spi, lp);
1922+
1923+ rc = at86rf230_fill_data(spi);
1924+ if (rc)
1925+ goto err_fill;
1926+
1927+ if (gpio_is_valid(lp->rstn)) {
1928+ rc = gpio_request(lp->rstn, "rstn");
1929+ if (rc)
1930+ goto err_rstn;
1931+ }
1932+
1933+ if (gpio_is_valid(lp->slp_tr)) {
1934+ rc = gpio_request(lp->slp_tr, "slp_tr");
1935+ if (rc)
1936+ goto err_slp_tr;
1937+ }
1938+
1939+ if (gpio_is_valid(lp->rstn)) {
1940+ rc = gpio_direction_output(lp->rstn, 1);
1941+ if (rc)
1942+ goto err_gpio_dir;
1943+ }
1944+
1945+ if (gpio_is_valid(lp->slp_tr)) {
1946+ rc = gpio_direction_output(lp->slp_tr, 0);
1947+ if (rc)
1948+ goto err_gpio_dir;
1949+ }
1950+
1951+ /* Reset */
1952+ if (lp->reset)
1953+ lp->reset(lp->reset_data);
1954+ else {
1955+ msleep(1);
1956+ gpio_set_value(lp->rstn, 0);
1957+ msleep(1);
1958+ gpio_set_value(lp->rstn, 1);
1959+ msleep(1);
1960+ }
1961+
1962+ rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
1963+ if (rc)
1964+ goto err_gpio_dir;
1965+ rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
1966+ if (rc)
1967+ goto err_gpio_dir;
1968+
1969+ if (man_id_1 != 0x00 || man_id_0 != 0x1f) {
1970+ dev_err(&spi->dev, "Non-Atmel device found (MAN_ID:"
1971+ "%02x %02x)\n", man_id_1, man_id_0);
1972+ rc = -EINVAL;
1973+ goto err_gpio_dir;
1974+ }
1975+
1976+ rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part);
1977+ if (rc)
1978+ goto err_gpio_dir;
1979+
1980+ rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
1981+ if (rc)
1982+ goto err_gpio_dir;
1983+
1984+ switch (lp->part) {
1985+ case 2:
1986+ chip = "at86rf230";
1987+ /* supported = 1; FIXME: should be easy to support; */
1988+ break;
1989+ case 3:
1990+ chip = "at86rf231";
1991+ supported = 1;
1992+ break;
1993+ default:
1994+ chip = "UNKNOWN";
1995+ break;
1996+ }
1997+
1998+ dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers);
1999+ if (!supported) {
2000+ rc = -ENOTSUPP;
2001+ goto err_gpio_dir;
2002+ }
2003+
2004+ rc = at86rf230_hw_init(lp);
2005+ if (rc)
2006+ goto err_gpio_dir;
2007+
2008+ rc = request_irq(spi->irq, at86rf230_isr, IRQF_SHARED,
2009+ dev_name(&spi->dev), lp);
2010+ if (rc)
2011+ goto err_gpio_dir;
2012+
2013+ dev_dbg(&spi->dev, "registered at86rf230\n");
2014+
2015+ rc = ieee802154_register_device(lp->dev);
2016+ if (rc)
2017+ goto err_irq;
2018+
2019+ return rc;
2020+
2021+err_irq:
2022+ disable_irq(spi->irq);
2023+ flush_work(&lp->irqwork);
2024+ free_irq(spi->irq, lp);
2025+err_gpio_dir:
2026+ if (gpio_is_valid(lp->slp_tr))
2027+ gpio_free(lp->slp_tr);
2028+err_slp_tr:
2029+ if (gpio_is_valid(lp->rstn))
2030+ gpio_free(lp->rstn);
2031+err_rstn:
2032+err_fill:
2033+ spi_set_drvdata(spi, NULL);
2034+ mutex_destroy(&lp->bmux);
2035+ ieee802154_free_device(lp->dev);
2036+ return rc;
2037+}
2038+
2039+static int __devexit at86rf230_remove(struct spi_device *spi)
2040+{
2041+ struct at86rf230_local *lp = spi_get_drvdata(spi);
2042+
2043+ /*
2044+ * @@@ this looks wrong - what if a frame arrives before
2045+ * disable_irq ? -- wa
2046+ */
2047+ ieee802154_unregister_device(lp->dev);
2048+
2049+ disable_irq(spi->irq);
2050+ flush_work(&lp->irqwork);
2051+ free_irq(spi->irq, lp);
2052+
2053+ if (gpio_is_valid(lp->slp_tr))
2054+ gpio_free(lp->slp_tr);
2055+ if (gpio_is_valid(lp->rstn))
2056+ gpio_free(lp->rstn);
2057+
2058+ spi_set_drvdata(spi, NULL);
2059+ mutex_destroy(&lp->bmux);
2060+ ieee802154_free_device(lp->dev);
2061+
2062+ dev_dbg(&spi->dev, "unregistered at86rf230\n");
2063+ return 0;
2064+}
2065+
2066+static struct spi_driver at86rf230_driver = {
2067+ .driver = {
2068+ .name = "at86rf230",
2069+ .owner = THIS_MODULE,
2070+ },
2071+ .probe = at86rf230_probe,
2072+ .remove = __devexit_p(at86rf230_remove),
2073+ .suspend = at86rf230_suspend,
2074+ .resume = at86rf230_resume,
2075+};
2076+
2077+static int __init at86rf230_init(void)
2078+{
2079+ return spi_register_driver(&at86rf230_driver);
2080+}
2081+module_init(at86rf230_init);
2082+
2083+static void __exit at86rf230_exit(void)
2084+{
2085+ spi_unregister_driver(&at86rf230_driver);
2086+}
2087+module_exit(at86rf230_exit);
2088+
2089+MODULE_DESCRIPTION("AT86RF230 Transceiver Driver");
2090+MODULE_LICENSE("GPL v2");
2091diff --git a/drivers/ieee802154/at86rf230.h b/drivers/ieee802154/at86rf230.h
2092new file mode 100644
2093index 0000000..fcb0e11
2094--- /dev/null
2095@@ -0,0 +1,211 @@
2096+/*
2097+ * AT86RF230/RF231 register and protocol definitions
2098+ *
2099+ * Copyright (C) 2009 Siemens AG
2100+ *
2101+ * This program is free software; you can redistribute it and/or modify
2102+ * it under the terms of the GNU General Public License version 2
2103+ * as published by the Free Software Foundation.
2104+ *
2105+ * This program is distributed in the hope that it will be useful,
2106+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2107+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2108+ * GNU General Public License for more details.
2109+ *
2110+ * You should have received a copy of the GNU General Public License along
2111+ * with this program; if not, write to the Free Software Foundation, Inc.,
2112+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2113+ *
2114+ * Written by:
2115+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
2116+ */
2117+
2118+#ifndef ATR86F230_H
2119+#define ATR86F230_H
2120+
2121+#define RG_TRX_STATUS (0x01)
2122+#define SR_TRX_STATUS 0x01, 0x1f, 0
2123+#define SR_RESERVED_01_3 0x01, 0x20, 5
2124+#define SR_CCA_STATUS 0x01, 0x40, 6
2125+#define SR_CCA_DONE 0x01, 0x80, 7
2126+#define RG_TRX_STATE (0x02)
2127+#define SR_TRX_CMD 0x02, 0x1f, 0
2128+#define SR_TRAC_STATUS 0x02, 0xe0, 5
2129+#define RG_TRX_CTRL_0 (0x03)
2130+#define SR_CLKM_CTRL 0x03, 0x07, 0
2131+#define SR_CLKM_SHA_SEL 0x03, 0x08, 3
2132+#define SR_PAD_IO_CLKM 0x03, 0x30, 4
2133+#define SR_PAD_IO 0x03, 0xc0, 6
2134+#define RG_TRX_CTRL_1 (0x04)
2135+#define SR_IRQ_POLARITY 0x04, 0x01, 0
2136+#define SR_IRQ_MASK_MODE 0x04, 0x02, 1
2137+#define SR_SPI_CMD_MODE 0x04, 0x0c, 2
2138+#define SR_RX_BL_CTRL 0x04, 0x10, 4
2139+#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5
2140+#define SR_IRQ_2_EXT_EN 0x04, 0x40, 6
2141+#define SR_PA_EXT_EN 0x04, 0x80, 7
2142+#define RG_PHY_TX_PWR (0x05)
2143+#define SR_TX_PWR 0x05, 0x0f, 0
2144+#define SR_PA_LT 0x05, 0x30, 4
2145+#define SR_PA_BUF_LT 0x05, 0xc0, 6
2146+#define RG_PHY_RSSI (0x06)
2147+#define SR_RSSI 0x06, 0x1f, 0
2148+#define SR_RND_VALUE 0x06, 0x60, 5
2149+#define SR_RX_CRC_VALID 0x06, 0x80, 7
2150+#define RG_PHY_ED_LEVEL (0x07)
2151+#define SR_ED_LEVEL 0x07, 0xff, 0
2152+#define RG_PHY_CC_CCA (0x08)
2153+#define SR_CHANNEL 0x08, 0x1f, 0
2154+#define SR_CCA_MODE 0x08, 0x60, 5
2155+#define SR_CCA_REQUEST 0x08, 0x80, 7
2156+#define RG_CCA_THRES (0x09)
2157+#define SR_CCA_ED_THRES 0x09, 0x0f, 0
2158+#define SR_RESERVED_09_1 0x09, 0xf0, 4
2159+#define RG_RX_CTRL (0x0a)
2160+#define SR_PDT_THRES 0x0a, 0x0f, 0
2161+#define SR_RESERVED_0a_1 0x0a, 0xf0, 4
2162+#define RG_SFD_VALUE (0x0b)
2163+#define SR_SFD_VALUE 0x0b, 0xff, 0
2164+#define RG_TRX_CTRL_2 (0x0c)
2165+#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0
2166+#define SR_RESERVED_0c_2 0x0c, 0x7c, 2
2167+#define SR_RX_SAFE_MODE 0x0c, 0x80, 7
2168+#define RG_ANT_DIV (0x0d)
2169+#define SR_ANT_CTRL 0x0d, 0x03, 0
2170+#define SR_ANT_EXT_SW_EN 0x0d, 0x04, 2
2171+#define SR_ANT_DIV_EN 0x0d, 0x08, 3
2172+#define SR_RESERVED_0d_2 0x0d, 0x70, 4
2173+#define SR_ANT_SEL 0x0d, 0x80, 7
2174+#define RG_IRQ_MASK (0x0e)
2175+#define SR_IRQ_MASK 0x0e, 0xff, 0
2176+#define RG_IRQ_STATUS (0x0f)
2177+#define SR_IRQ_0_PLL_LOCK 0x0f, 0x01, 0
2178+#define SR_IRQ_1_PLL_UNLOCK 0x0f, 0x02, 1
2179+#define SR_IRQ_2_RX_START 0x0f, 0x04, 2
2180+#define SR_IRQ_3_TRX_END 0x0f, 0x08, 3
2181+#define SR_IRQ_4_CCA_ED_DONE 0x0f, 0x10, 4
2182+#define SR_IRQ_5_AMI 0x0f, 0x20, 5
2183+#define SR_IRQ_6_TRX_UR 0x0f, 0x40, 6
2184+#define SR_IRQ_7_BAT_LOW 0x0f, 0x80, 7
2185+#define RG_VREG_CTRL (0x10)
2186+#define SR_RESERVED_10_6 0x10, 0x03, 0
2187+#define SR_DVDD_OK 0x10, 0x04, 2
2188+#define SR_DVREG_EXT 0x10, 0x08, 3
2189+#define SR_RESERVED_10_3 0x10, 0x30, 4
2190+#define SR_AVDD_OK 0x10, 0x40, 6
2191+#define SR_AVREG_EXT 0x10, 0x80, 7
2192+#define RG_BATMON (0x11)
2193+#define SR_BATMON_VTH 0x11, 0x0f, 0
2194+#define SR_BATMON_HR 0x11, 0x10, 4
2195+#define SR_BATMON_OK 0x11, 0x20, 5
2196+#define SR_RESERVED_11_1 0x11, 0xc0, 6
2197+#define RG_XOSC_CTRL (0x12)
2198+#define SR_XTAL_TRIM 0x12, 0x0f, 0
2199+#define SR_XTAL_MODE 0x12, 0xf0, 4
2200+#define RG_RX_SYN (0x15)
2201+#define SR_RX_PDT_LEVEL 0x15, 0x0f, 0
2202+#define SR_RESERVED_15_2 0x15, 0x70, 4
2203+#define SR_RX_PDT_DIS 0x15, 0x80, 7
2204+#define RG_XAH_CTRL_1 (0x17)
2205+#define SR_RESERVED_17_8 0x17, 0x01, 0
2206+#define SR_AACK_PROM_MODE 0x17, 0x02, 1
2207+#define SR_AACK_ACK_TIME 0x17, 0x04, 2
2208+#define SR_RESERVED_17_5 0x17, 0x08, 3
2209+#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4
2210+#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5
2211+#define SR_RESERVED_17_2 0x17, 0x40, 6
2212+#define SR_RESERVED_17_1 0x17, 0x80, 7
2213+#define RG_FTN_CTRL (0x18)
2214+#define SR_RESERVED_18_2 0x18, 0x7f, 0
2215+#define SR_FTN_START 0x18, 0x80, 7
2216+#define RG_PLL_CF (0x1a)
2217+#define SR_RESERVED_1a_2 0x1a, 0x7f, 0
2218+#define SR_PLL_CF_START 0x1a, 0x80, 7
2219+#define RG_PLL_DCU (0x1b)
2220+#define SR_RESERVED_1b_3 0x1b, 0x3f, 0
2221+#define SR_RESERVED_1b_2 0x1b, 0x40, 6
2222+#define SR_PLL_DCU_START 0x1b, 0x80, 7
2223+#define RG_PART_NUM (0x1c)
2224+#define SR_PART_NUM 0x1c, 0xff, 0
2225+#define RG_VERSION_NUM (0x1d)
2226+#define SR_VERSION_NUM 0x1d, 0xff, 0
2227+#define RG_MAN_ID_0 (0x1e)
2228+#define SR_MAN_ID_0 0x1e, 0xff, 0
2229+#define RG_MAN_ID_1 (0x1f)
2230+#define SR_MAN_ID_1 0x1f, 0xff, 0
2231+#define RG_SHORT_ADDR_0 (0x20)
2232+#define SR_SHORT_ADDR_0 0x20, 0xff, 0
2233+#define RG_SHORT_ADDR_1 (0x21)
2234+#define SR_SHORT_ADDR_1 0x21, 0xff, 0
2235+#define RG_PAN_ID_0 (0x22)
2236+#define SR_PAN_ID_0 0x22, 0xff, 0
2237+#define RG_PAN_ID_1 (0x23)
2238+#define SR_PAN_ID_1 0x23, 0xff, 0
2239+#define RG_IEEE_ADDR_0 (0x24)
2240+#define SR_IEEE_ADDR_0 0x24, 0xff, 0
2241+#define RG_IEEE_ADDR_1 (0x25)
2242+#define SR_IEEE_ADDR_1 0x25, 0xff, 0
2243+#define RG_IEEE_ADDR_2 (0x26)
2244+#define SR_IEEE_ADDR_2 0x26, 0xff, 0
2245+#define RG_IEEE_ADDR_3 (0x27)
2246+#define SR_IEEE_ADDR_3 0x27, 0xff, 0
2247+#define RG_IEEE_ADDR_4 (0x28)
2248+#define SR_IEEE_ADDR_4 0x28, 0xff, 0
2249+#define RG_IEEE_ADDR_5 (0x29)
2250+#define SR_IEEE_ADDR_5 0x29, 0xff, 0
2251+#define RG_IEEE_ADDR_6 (0x2a)
2252+#define SR_IEEE_ADDR_6 0x2a, 0xff, 0
2253+#define RG_IEEE_ADDR_7 (0x2b)
2254+#define SR_IEEE_ADDR_7 0x2b, 0xff, 0
2255+#define RG_XAH_CTRL_0 (0x2c)
2256+#define SR_SLOTTED_OPERATION 0x2c, 0x01, 0
2257+#define SR_MAX_CSMA_RETRIES 0x2c, 0x0e, 1
2258+#define SR_MAX_FRAME_RETRIES 0x2c, 0xf0, 4
2259+#define RG_CSMA_SEED_0 (0x2d)
2260+#define SR_CSMA_SEED_0 0x2d, 0xff, 0
2261+#define RG_CSMA_SEED_1 (0x2e)
2262+#define SR_CSMA_SEED_1 0x2e, 0x07, 0
2263+#define SR_AACK_I_AM_COORD 0x2e, 0x08, 3
2264+#define SR_AACK_DIS_ACK 0x2e, 0x10, 4
2265+#define SR_AACK_SET_PD 0x2e, 0x20, 5
2266+#define SR_AACK_FVN_MODE 0x2e, 0xc0, 6
2267+#define RG_CSMA_BE (0x2f)
2268+#define SR_MIN_BE 0x2f, 0x0f, 0
2269+#define SR_MAX_BE 0x2f, 0xf0, 4
2270+
2271+#define CMD_REG 0x80
2272+#define CMD_REG_MASK 0x3f
2273+#define CMD_WRITE 0x40
2274+#define CMD_FB 0x20
2275+
2276+#define IRQ_BAT_LOW (1 << 7)
2277+#define IRQ_TRX_UR (1 << 6)
2278+#define IRQ_AMI (1 << 5)
2279+#define IRQ_CCA_ED (1 << 4)
2280+#define IRQ_TRX_END (1 << 3)
2281+#define IRQ_RX_START (1 << 2)
2282+#define IRQ_PLL_UNL (1 << 1)
2283+#define IRQ_PLL_LOCK (1 << 0)
2284+
2285+#define STATE_P_ON 0x00 /* BUSY */
2286+#define STATE_BUSY_RX 0x01
2287+#define STATE_BUSY_TX 0x02
2288+#define STATE_FORCE_TRX_OFF 0x03
2289+#define STATE_FORCE_TX_ON 0x04 /* IDLE */
2290+/* 0x05 */ /* INVALID_PARAMETER */
2291+#define STATE_RX_ON 0x06
2292+/* 0x07 */ /* SUCCESS */
2293+#define STATE_TRX_OFF 0x08
2294+#define STATE_TX_ON 0x09
2295+/* 0x0a - 0x0e */ /* 0x0a - UNSUPPORTED_ATTRIBUTE */
2296+#define STATE_SLEEP 0x0F
2297+#define STATE_BUSY_RX_AACK 0x11
2298+#define STATE_BUSY_TX_ARET 0x12
2299+#define STATE_BUSY_RX_AACK_ON 0x16
2300+#define STATE_BUSY_TX_ARET_ON 0x19
2301+#define STATE_RX_ON_NOCLK 0x1C
2302+#define STATE_RX_AACK_ON_NOCLK 0x1D
2303+#define STATE_BUSY_RX_AACK_NOCLK 0x1E
2304+#define STATE_TRANSITION_IN_PROGRESS 0x1F
2305+
2306+#endif /* !ATR86F230_H */
2307diff --git a/drivers/ieee802154/cc2420.c b/drivers/ieee802154/cc2420.c
2308new file mode 100644
2309index 0000000..50761de
2310--- /dev/null
2311@@ -0,0 +1,859 @@
2312+/*
2313+ * This program is free software; you can redistribute it and/or modify
2314+ * it under the terms of the GNU General Public License version 2
2315+ * as published by the Free Software Foundation.
2316+ *
2317+ * This program is distributed in the hope that it will be useful,
2318+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2319+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2320+ * GNU General Public License for more details.
2321+ *
2322+ * You should have received a copy of the GNU General Public License along
2323+ * with this program; if not, write to the Free Software Foundation, Inc.,
2324+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2325+ *
2326+ * Author: Jonathan Cameron <jic23@cam.ac.uk>
2327+ *
2328+ * Modified 2010: xue liu <liuxuenetmail@gmail.com>
2329+ */
2330+
2331+#include <linux/kernel.h>
2332+#include <linux/module.h>
2333+#include <linux/mutex.h>
2334+#include <linux/spinlock.h>
2335+#include <linux/gpio.h>
2336+#include <linux/delay.h>
2337+#include <linux/interrupt.h>
2338+#include <linux/workqueue.h>
2339+#include <linux/spi/spi.h>
2340+#include <linux/spi/cc2420.h>
2341+#include <linux/skbuff.h>
2342+#include <linux/irq.h>
2343+#include <net/mac802154.h>
2344+#include <net/wpan-phy.h>
2345+
2346+#define CC2420_WRITEREG(x) (x)
2347+#define CC2420_READREG(x) (0x40 | x)
2348+#define CC2420_RAMADDR(x) ((x & 0x7F) | 0x80)
2349+#define CC2420_RAMBANK(x) ((x >> 1) & 0xc0)
2350+#define CC2420_WRITERAM(x) (x)
2351+#define CC2420_READRAM(x) (0x20 | x)
2352+
2353+#define CC2420_FREQ_MASK 0x3FF
2354+#define CC2420_ADR_DECODE_MASK 0x0B00
2355+#define CC2420_FIFOP_THR_MASK 0x003F
2356+#define CC2420_CRC_MASK 0x80
2357+#define CC2420_RSSI_MASK 0x7F
2358+#define CC2420_FSMSTATE_MASK 0x2F
2359+
2360+#define CC2420_MANFIDLOW 0x233D
2361+#define CC2420_MANFIDHIGH 0x3000 /* my chip appears to version 3 - broaden this with testing */
2362+
2363+#define RSSI_OFFSET 45
2364+
2365+#define STATE_PDOWN 0
2366+#define STATE_IDLE 1
2367+#define STATE_RX_CALIBRATE 2
2368+#define STATE_RX_CALIBRATE2 40
2369+
2370+#define STATE_RX_SFD_SEARCH_MIN 3
2371+#define STATE_RX_SFD_SEARCH_MAX 6
2372+#define STATE_RX_FRAME 16
2373+#define STATE_RX_FRAME2 40
2374+#define STATE_RX_WAIT 14
2375+#define STATE_RX_OVERFLOW 17
2376+#define STATE_TX_ACK_CALIBRATE 48
2377+#define STATE_TX_ACK_PREAMBLE_MIN 49
2378+#define STATE_TX_ACK_PREAMBLE_MAX 51
2379+#define STATE_TX_ACK_MIN 52
2380+#define STATE_TX_ACK_MAX 54
2381+#define STATE_TX_CALIBRATE 32
2382+#define STATE_TX_PREAMBLE_MIN 34
2383+#define STATE_TX_PREAMBLE_MAX 36
2384+#define STATE_TX_FRAME_MIN 37
2385+#define STATE_TX_FRAME_MAX 39
2386+#define STATE_TX_UNDERFLOW 56
2387+
2388+struct cc2420_local {
2389+ struct cc2420_platform_data *pdata;
2390+ struct spi_device *spi;
2391+ struct ieee802154_dev *dev;
2392+ u8 *buf;
2393+ struct mutex bmux;
2394+ int fifop_irq;
2395+ int sfd_irq;
2396+ struct work_struct fifop_irqwork;
2397+ struct work_struct sfd_irqwork;
2398+ spinlock_t lock;
2399+ unsigned irq_disabled:1;/* P:lock */
2400+ unsigned is_tx:1; /* P:lock */
2401+
2402+ struct completion tx_complete;
2403+};
2404+static int cc2420_get_status(struct cc2420_local *lp, u8 *status)
2405+{
2406+ int ret;
2407+ struct spi_message msg;
2408+ struct spi_transfer xfer = {
2409+ .len = 1,
2410+ .tx_buf = lp->buf,
2411+ .rx_buf = lp->buf,
2412+ };
2413+ spi_message_init(&msg);
2414+ spi_message_add_tail(&xfer, &msg);
2415+ mutex_lock(&lp->bmux);
2416+ lp->buf[0] = CC2420_WRITEREG(CC2420_SNOP);
2417+ dev_vdbg(&lp->spi->dev, "get status command buf[0] = %02x\n", lp->buf[0]);
2418+ ret = spi_sync(lp->spi, &msg);
2419+ if (!ret)
2420+ *status = lp->buf[0];
2421+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2422+ mutex_unlock(&lp->bmux);
2423+ return ret;
2424+
2425+}
2426+static int cc2420_cmd_strobe(struct cc2420_local *lp,
2427+ u8 addr)
2428+{
2429+ int ret;
2430+ u8 status = 0xf;
2431+ struct spi_message msg;
2432+ struct spi_transfer xfer = {
2433+ .len = 1,
2434+ .tx_buf = lp->buf,
2435+ .rx_buf = lp->buf,
2436+ };
2437+ spi_message_init(&msg);
2438+ spi_message_add_tail(&xfer, &msg);
2439+ mutex_lock(&lp->bmux);
2440+ lp->buf[0] = CC2420_WRITEREG(addr);
2441+ dev_vdbg(&lp->spi->dev, "cmd strobe buf[0] = %02x\n", lp->buf[0]);
2442+ ret = spi_sync(lp->spi, &msg);
2443+ if (!ret)
2444+ status = lp->buf[0];
2445+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2446+
2447+ mutex_unlock(&lp->bmux);
2448+
2449+ return ret;
2450+}
2451+
2452+static int cc2420_read_16_bit_reg(struct cc2420_local *lp,
2453+ u8 addr, u16 *data)
2454+{
2455+ int ret;
2456+ struct spi_message msg;
2457+ struct spi_transfer xfer = {
2458+ .len = 3,
2459+ .tx_buf = lp->buf,
2460+ .rx_buf = lp->buf,
2461+ };
2462+
2463+ spi_message_init(&msg);
2464+ spi_message_add_tail(&xfer, &msg);
2465+ mutex_lock(&lp->bmux);
2466+ lp->buf[0] = CC2420_READREG(addr);
2467+ dev_vdbg(&lp->spi->dev, "readreg addr buf[0] = %02x\n", lp->buf[0]);
2468+ ret = spi_sync(lp->spi, &msg);
2469+ dev_dbg(&lp->spi->dev, "status = %d\n", ret);
2470+ mutex_unlock(&lp->bmux);
2471+ dev_dbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2472+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2473+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2474+ if (!ret)
2475+ *data = ((u16) (lp->buf[1]) << 8) | lp->buf[2];
2476+ return ret;
2477+}
2478+
2479+static int cc2420_write_16_bit_reg_partial(struct cc2420_local *lp,
2480+ u8 addr, u16 data, u16 mask)
2481+{
2482+ int ret;
2483+ struct spi_message msg;
2484+ struct spi_transfer xfer = {
2485+ .len = 3,
2486+ .tx_buf = lp->buf,
2487+ .rx_buf = lp->buf,
2488+ };
2489+ dev_dbg(&lp->spi->dev, "data = %x\n", data);
2490+ dev_dbg(&lp->spi->dev, "mask = %x\n", mask);
2491+ spi_message_init(&msg);
2492+ spi_message_add_tail(&xfer, &msg);
2493+ mutex_lock(&lp->bmux);
2494+ lp->buf[0] = CC2420_READREG(addr);
2495+ dev_vdbg(&lp->spi->dev, "read addr buf[0] = %02x\n", lp->buf[0]);
2496+ ret = spi_sync(lp->spi, &msg);
2497+ if (ret)
2498+ goto err_ret;
2499+ dev_dbg(&lp->spi->dev, "read buf[0] = %02x\n", lp->buf[0]);
2500+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2501+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2502+
2503+ lp->buf[0] = CC2420_WRITEREG(addr);
2504+
2505+ lp->buf[1] &= ~(mask >> 8);
2506+ lp->buf[2] &= ~(mask & 0xFF);
2507+ lp->buf[1] |= (mask >> 8) & (data >> 8);
2508+ lp->buf[2] |= (mask & 0xFF) & (data & 0xFF);
2509+ dev_vdbg(&lp->spi->dev, "writereg addr buf[0] = %02x\n", lp->buf[0]);
2510+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2511+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2512+ ret = spi_sync(lp->spi, &msg);
2513+ if (ret)
2514+ goto err_ret;
2515+ dev_dbg(&lp->spi->dev, "return status buf[0] = %02x\n", lp->buf[0]);
2516+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2517+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2518+
2519+err_ret:
2520+ mutex_unlock(&lp->bmux);
2521+ return ret;
2522+}
2523+
2524+static int cc2420_channel(struct ieee802154_dev *dev, int page, int channel)
2525+{
2526+ struct cc2420_local *lp = dev->priv;
2527+ int ret;
2528+
2529+ might_sleep();
2530+ dev_dbg(&lp->spi->dev, "trying to set channel\n");
2531+
2532+ BUG_ON(page != 0);
2533+ BUG_ON(channel < CC2420_MIN_CHANNEL);
2534+ BUG_ON(channel > CC2420_MAX_CHANNEL);
2535+
2536+ ret = cc2420_write_16_bit_reg_partial(lp, CC2420_FSCTRL, 357 + 5*(channel - 11), CC2420_FREQ_MASK);
2537+
2538+ dev->phy->current_channel = channel;
2539+ return ret;
2540+}
2541+
2542+static int cc2420_write_ram(struct cc2420_local *lp, u16 addr, u8 len, u8 *data)
2543+{
2544+ int status;
2545+ struct spi_message msg;
2546+ struct spi_transfer xfer_head = {
2547+ .len = 2,
2548+ .tx_buf = lp->buf,
2549+ .rx_buf = lp->buf,
2550+ };
2551+ struct spi_transfer xfer_buf = {
2552+ .len = len,
2553+ .tx_buf = data,
2554+ };
2555+
2556+ mutex_lock(&lp->bmux);
2557+ lp->buf[0] = CC2420_RAMADDR(addr);
2558+ lp->buf[1] = CC2420_WRITERAM(CC2420_RAMBANK(addr));
2559+ dev_dbg(&lp->spi->dev, "write ram addr buf[0] = %02x\n", lp->buf[0]);
2560+ dev_dbg(&lp->spi->dev, "ram bank buf[1] = %02x\n", lp->buf[1]);
2561+
2562+ spi_message_init(&msg);
2563+ spi_message_add_tail(&xfer_head, &msg);
2564+ spi_message_add_tail(&xfer_buf, &msg);
2565+
2566+ status = spi_sync(lp->spi, &msg);
2567+ dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
2568+ if (msg.status)
2569+ status = msg.status;
2570+ dev_dbg(&lp->spi->dev, "cc2420 status = %02x\n", lp->buf[0]);
2571+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2572+
2573+ mutex_unlock(&lp->bmux);
2574+ return status;
2575+}
2576+
2577+static int cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
2578+{
2579+ int status;
2580+ /* Length byte must include FCS even if calculated in hardware */
2581+ int len_byte = len + 2;
2582+ struct spi_message msg;
2583+ struct spi_transfer xfer_head = {
2584+ .len = 1,
2585+ .tx_buf = lp->buf,
2586+ .rx_buf = lp->buf,
2587+ };
2588+ struct spi_transfer xfer_len = {
2589+ .len = 1,
2590+ .tx_buf = &len_byte,
2591+ };
2592+ struct spi_transfer xfer_buf = {
2593+ .len = len,
2594+ .tx_buf = data,
2595+ };
2596+
2597+ mutex_lock(&lp->bmux);
2598+ lp->buf[0] = CC2420_WRITEREG(CC2420_TXFIFO);
2599+ dev_vdbg(&lp->spi->dev, "TX_FIFO addr buf[0] = %02x\n", lp->buf[0]);
2600+
2601+ spi_message_init(&msg);
2602+ spi_message_add_tail(&xfer_head, &msg);
2603+ spi_message_add_tail(&xfer_len, &msg);
2604+ spi_message_add_tail(&xfer_buf, &msg);
2605+
2606+ status = spi_sync(lp->spi, &msg);
2607+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2608+ if (msg.status)
2609+ status = msg.status;
2610+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2611+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2612+
2613+ mutex_unlock(&lp->bmux);
2614+ return status;
2615+}
2616+
2617+static int
2618+cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
2619+{
2620+ int status;
2621+ struct spi_message msg;
2622+ struct spi_transfer xfer_head = {
2623+ .len = 2,
2624+ .tx_buf = lp->buf,
2625+ .rx_buf = lp->buf,
2626+ };
2627+ struct spi_transfer xfer_buf = {
2628+ .len = *len,
2629+ .rx_buf = data,
2630+ };
2631+
2632+ mutex_lock(&lp->bmux);
2633+ lp->buf[0] = CC2420_READREG(CC2420_RXFIFO);
2634+ lp->buf[1] = 0x00;
2635+ dev_vdbg(&lp->spi->dev, "read rxfifo buf[0] = %02x\n", lp->buf[0]);
2636+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2637+ spi_message_init(&msg);
2638+ spi_message_add_tail(&xfer_head, &msg);
2639+ spi_message_add_tail(&xfer_buf, &msg);
2640+
2641+ status = spi_sync(lp->spi, &msg);
2642+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2643+ if (msg.status)
2644+ status = msg.status;
2645+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2646+ dev_vdbg(&lp->spi->dev, "return status buf[0] = %02x\n", lp->buf[0]);
2647+ dev_vdbg(&lp->spi->dev, "length buf[1] = %02x\n", lp->buf[1]);
2648+
2649+ *lqi = data[lp->buf[1] - 1] & 0x7f;
2650+ *len = lp->buf[1]; /* it should be less than 130 */
2651+
2652+ mutex_unlock(&lp->bmux);
2653+
2654+ return status;
2655+}
2656+
2657+
2658+static int cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
2659+{
2660+ struct cc2420_local *lp = dev->priv;
2661+ int rc;
2662+ unsigned long flags;
2663+ u8 status = 0;
2664+
2665+ pr_debug("%s\n", __func__);
2666+
2667+ might_sleep();
2668+
2669+ rc = cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2670+ if (rc)
2671+ goto err_rx;
2672+ rc = cc2420_write_txfifo(lp, skb->data, skb->len);
2673+ if (rc)
2674+ goto err_rx;
2675+
2676+ /* TODO: test CCA pin */
2677+
2678+ rc = cc2420_get_status(lp, &status);
2679+ if (rc)
2680+ goto err_rx;
2681+
2682+ if (status & CC2420_STATUS_TX_UNDERFLOW) {
2683+ dev_err(&lp->spi->dev, "cc2420 tx underflow!\n");
2684+ goto err_rx;
2685+ }
2686+
2687+ spin_lock_irqsave(&lp->lock, flags);
2688+ BUG_ON(lp->is_tx);
2689+ lp->is_tx = 1;
2690+ INIT_COMPLETION(lp->tx_complete);
2691+ spin_unlock_irqrestore(&lp->lock, flags);
2692+
2693+ rc = cc2420_cmd_strobe(lp, CC2420_STXONCCA);
2694+ if (rc)
2695+ goto err;
2696+
2697+ rc = wait_for_completion_interruptible(&lp->tx_complete);
2698+ if (rc < 0)
2699+ goto err;
2700+
2701+ cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2702+ cc2420_cmd_strobe(lp, CC2420_SRXON);
2703+
2704+ return rc;
2705+
2706+err:
2707+ spin_lock_irqsave(&lp->lock, flags);
2708+ lp->is_tx = 0;
2709+ spin_unlock_irqrestore(&lp->lock, flags);
2710+err_rx:
2711+ cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2712+ cc2420_cmd_strobe(lp, CC2420_SRXON);
2713+ return rc;
2714+}
2715+
2716+static int cc2420_rx(struct cc2420_local *lp)
2717+{
2718+ u8 len = 128;
2719+ u8 lqi = 0; /* link quality */
2720+ int rc;
2721+ struct sk_buff *skb;
2722+
2723+ skb = alloc_skb(len, GFP_KERNEL);
2724+ if (!skb)
2725+ return -ENOMEM;
2726+
2727+ rc = cc2420_read_rxfifo(lp, skb_put(skb, len), &len, &lqi);
2728+ if (len < 2) {
2729+ kfree_skb(skb);
2730+ return -EINVAL;
2731+ }
2732+
2733+ /* Clip last two bytes. When using hardware FCS they get replaced with
2734+ * correlation value, FCS flag and RSSI value */
2735+ skb_trim(skb, len-2);
2736+
2737+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
2738+
2739+ dev_dbg(&lp->spi->dev, "RXFIFO: %d %d %x\n", rc, len, lqi);
2740+
2741+ return 0;
2742+}
2743+
2744+static int
2745+cc2420_set_hw_addr_filt(struct ieee802154_dev *dev,
2746+ struct ieee802154_hw_addr_filt *filt,
2747+ unsigned long changed)
2748+{
2749+ struct cc2420_local *lp = dev->priv;
2750+ u16 reg;
2751+
2752+ might_sleep();
2753+
2754+ if (changed & IEEE802515_IEEEADDR_CHANGED)
2755+ cc2420_write_ram(lp, CC2420_RAM_IEEEADR,
2756+ IEEE802154_ALEN,
2757+ filt->ieee_addr);
2758+
2759+ if (changed & IEEE802515_SADDR_CHANGED) {
2760+ u8 short_addr[2];
2761+ short_addr[0] = filt->short_addr & 0xff;/* LSB */
2762+ short_addr[1] = filt->short_addr >> 8; /* MSB */
2763+ cc2420_write_ram(lp, CC2420_RAM_SHORTADR,
2764+ sizeof(short_addr),
2765+ short_addr);
2766+ }
2767+
2768+ if (changed & IEEE802515_PANID_CHANGED) {
2769+ u8 panid[2];
2770+ panid[0] = filt->pan_id & 0xff; /* LSB */
2771+ panid[1] = filt->pan_id >> 8; /* MSB */
2772+ cc2420_write_ram(lp, CC2420_RAM_PANID,
2773+ sizeof(panid),
2774+ panid);
2775+ }
2776+
2777+ if (changed & IEEE802515_PANC_CHANGED) {
2778+ cc2420_read_16_bit_reg(lp, CC2420_MDMCTRL0, &reg);
2779+ if (filt->pan_coord)
2780+ reg |= 1 << CC2420_MDMCTRL0_PANCRD;
2781+ else
2782+ reg &= ~(1 << CC2420_MDMCTRL0_PANCRD);
2783+ cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
2784+ reg, 1 << CC2420_MDMCTRL0_PANCRD);
2785+ }
2786+
2787+ return 0;
2788+}
2789+
2790+static int cc2420_ed(struct ieee802154_dev *dev, u8 *level)
2791+{
2792+ struct cc2420_local *lp = dev->priv;
2793+ u16 rssi;
2794+ int ret;
2795+ dev_dbg(&lp->spi->dev, "ed called\n");
2796+
2797+ ret = cc2420_read_16_bit_reg(lp, CC2420_RSSI, &rssi);
2798+ if (ret)
2799+ return ret;
2800+
2801+ /* P = RSSI_VAL + RSSI_OFFSET[dBm] */
2802+ *level = (rssi & CC2420_RSSI_MASK) + RSSI_OFFSET;
2803+ return ret;
2804+}
2805+
2806+static int cc2420_start(struct ieee802154_dev *dev)
2807+{
2808+ return cc2420_cmd_strobe(dev->priv, CC2420_SRXON);
2809+}
2810+
2811+static void cc2420_stop(struct ieee802154_dev *dev)
2812+{
2813+ cc2420_cmd_strobe(dev->priv, CC2420_SRFOFF);
2814+}
2815+
2816+static struct ieee802154_ops cc2420_ops = {
2817+ .owner = THIS_MODULE,
2818+ .xmit = cc2420_tx,
2819+ .ed = cc2420_ed,
2820+ .start = cc2420_start,
2821+ .stop = cc2420_stop,
2822+ .set_channel = cc2420_channel,
2823+ .set_hw_addr_filt = cc2420_set_hw_addr_filt,
2824+};
2825+
2826+static int cc2420_register(struct cc2420_local *lp)
2827+{
2828+ int ret = -ENOMEM;
2829+ lp->dev = ieee802154_alloc_device(sizeof(*lp), &cc2420_ops);
2830+ if (!lp->dev)
2831+ goto err_ret;
2832+
2833+ lp->dev->priv = lp;
2834+ lp->dev->parent = &lp->spi->dev;
2835+ //look this up.
2836+ lp->dev->extra_tx_headroom = 0;
2837+ //and this
2838+ //lp->dev->channel_mask = 0x7ff;
2839+ //and more.
2840+
2841+ /* We do support only 2.4 Ghz */
2842+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
2843+ lp->dev->flags = IEEE802154_HW_OMIT_CKSUM;
2844+
2845+ dev_dbg(&lp->spi->dev, "registered cc2420\n");
2846+ ret = ieee802154_register_device(lp->dev);
2847+ if (ret)
2848+ goto err_free_device;
2849+
2850+ return 0;
2851+err_free_device:
2852+ ieee802154_free_device(lp->dev);
2853+err_ret:
2854+ return ret;
2855+}
2856+
2857+static void cc2420_unregister(struct cc2420_local *lp)
2858+{
2859+ ieee802154_unregister_device(lp->dev);
2860+ //check this is needed
2861+ ieee802154_free_device(lp->dev);
2862+}
2863+
2864+static irqreturn_t cc2420_isr(int irq, void *data)
2865+{
2866+ struct cc2420_local *lp = data;
2867+
2868+ spin_lock(&lp->lock);
2869+ if (!lp->irq_disabled) {
2870+ disable_irq_nosync(irq);
2871+ lp->irq_disabled = 1;
2872+ }
2873+ spin_unlock(&lp->lock);
2874+
2875+ if (irq == lp->sfd_irq)
2876+ schedule_work(&lp->sfd_irqwork);
2877+
2878+ if (irq == lp->fifop_irq)
2879+ schedule_work(&lp->fifop_irqwork);
2880+
2881+ return IRQ_HANDLED;
2882+}
2883+
2884+static void cc2420_fifop_irqwork(struct work_struct *work)
2885+{
2886+ struct cc2420_local *lp
2887+ = container_of(work, struct cc2420_local, fifop_irqwork);
2888+ unsigned long flags;
2889+
2890+ dev_dbg(&lp->spi->dev, "fifop interrupt received\n");
2891+
2892+ if (gpio_get_value(lp->pdata->fifo))
2893+ cc2420_rx(lp);
2894+ else
2895+ dev_err(&lp->spi->dev, "rxfifo overflow\n");
2896+
2897+ cc2420_cmd_strobe(lp, CC2420_SFLUSHRX);
2898+ cc2420_cmd_strobe(lp, CC2420_SFLUSHRX);
2899+
2900+ spin_lock_irqsave(&lp->lock, flags);
2901+ if (lp->irq_disabled) {
2902+ lp->irq_disabled = 0;
2903+ enable_irq(lp->fifop_irq);
2904+ }
2905+ spin_unlock_irqrestore(&lp->lock, flags);
2906+}
2907+
2908+static void cc2420_sfd_irqwork(struct work_struct *work)
2909+{
2910+ struct cc2420_local *lp
2911+ = container_of(work, struct cc2420_local, sfd_irqwork);
2912+ unsigned long flags;
2913+
2914+ dev_dbg(&lp->spi->dev, "sfd interrupt received\n");
2915+
2916+ spin_lock_irqsave(&lp->lock, flags);
2917+ if (lp->is_tx) {
2918+ lp->is_tx = 0;
2919+ spin_unlock_irqrestore(&lp->lock, flags);
2920+ complete(&lp->tx_complete);
2921+ } else {
2922+ spin_unlock_irqrestore(&lp->lock, flags);
2923+ }
2924+
2925+ spin_lock_irqsave(&lp->lock, flags);
2926+ if (lp->irq_disabled) {
2927+ lp->irq_disabled = 0;
2928+ enable_irq(lp->sfd_irq);
2929+ }
2930+ spin_unlock_irqrestore(&lp->lock, flags);
2931+}
2932+
2933+static int cc2420_hw_init(struct cc2420_local *lp)
2934+{
2935+ int ret;
2936+ u16 state;
2937+ u8 status = 0xff;
2938+ int timeout = 500; /* 500us delay */
2939+ ret = cc2420_read_16_bit_reg(lp, CC2420_FSMSTATE, &state);
2940+ if (ret)
2941+ goto error_ret;
2942+ /* reset has occured prior to this, so there should be no other option */
2943+ if (state != STATE_PDOWN) {
2944+ ret = -EINVAL;
2945+ goto error_ret;
2946+ }
2947+ ret = cc2420_cmd_strobe(lp, CC2420_SXOSCON);
2948+ if (ret)
2949+ goto error_ret;
2950+
2951+ do {
2952+ ret = cc2420_get_status(lp, &status);
2953+ if (ret)
2954+ goto error_ret;
2955+ if (timeout-- <= 0) {
2956+ dev_err(&lp->spi->dev, "oscillator start failed!\n");
2957+ return ret;
2958+ }
2959+ udelay(1);
2960+ } while (!(status & CC2420_STATUS_XOSC16M_STABLE));
2961+
2962+ dev_info(&lp->spi->dev, "oscillator succesfully brought up\n");
2963+
2964+ return 0;
2965+error_ret:
2966+ return ret;
2967+}
2968+
2969+static int __devinit cc2420_probe(struct spi_device *spi)
2970+{
2971+ int ret;
2972+ u16 manidl, manidh;
2973+ struct cc2420_local *lp = kzalloc(sizeof *lp, GFP_KERNEL);
2974+ if (!lp) {
2975+ ret = -ENOMEM;
2976+ goto error_ret;
2977+ }
2978+
2979+ lp->pdata = spi->dev.platform_data;
2980+ if (!lp->pdata) {
2981+ dev_err(&spi->dev, "no platform data\n");
2982+ ret = -EINVAL;
2983+ goto err_free_local;
2984+ }
2985+ spi_set_drvdata(spi, lp);
2986+ mutex_init(&lp->bmux);
2987+ INIT_WORK(&lp->fifop_irqwork, cc2420_fifop_irqwork);
2988+ INIT_WORK(&lp->sfd_irqwork, cc2420_sfd_irqwork);
2989+ spin_lock_init(&lp->lock);
2990+ init_completion(&lp->tx_complete);
2991+
2992+ lp->spi = spi;
2993+ lp->buf = kmalloc(3*sizeof *lp->buf, GFP_KERNEL);
2994+ if (!lp->buf) {
2995+ ret = -ENOMEM;
2996+ goto err_free_local;
2997+ }
2998+
2999+ /* Request all the gpio's */
3000+ ret = gpio_request(lp->pdata->fifo, "fifo");
3001+ if (ret)
3002+ goto err_free_buf;
3003+ ret = gpio_request(lp->pdata->cca, "cca");
3004+ if (ret)
3005+ goto err_free_gpio_fifo;
3006+#if 0
3007+ /* This is causing problems as fifop is gpio 0 ? */
3008+ ret = gpio_request(lp->pdata->fifop, "fifop");
3009+ if (ret)
3010+ goto err_free_gpio_cca;
3011+#endif
3012+ ret = gpio_request(lp->pdata->sfd, "sfd");
3013+ if (ret)
3014+ goto err_free_gpio_fifop;
3015+ ret = gpio_request(lp->pdata->reset, "reset");
3016+ if (ret)
3017+ goto err_free_gpio_sfd;
3018+ ret = gpio_request(lp->pdata->vreg, "vreg");
3019+ if (ret)
3020+ goto err_free_gpio_reset;
3021+ /* Configure the gpios appropriately */
3022+
3023+ /* Enable the voltage regulator */
3024+ ret = gpio_direction_output(lp->pdata->vreg, 1);
3025+ if (ret)
3026+ goto err_free_gpio_reset;
3027+ udelay(600); /* Time for regulator to power up */
3028+ /* Toggle the reset */
3029+ ret = gpio_direction_output(lp->pdata->reset, 0);
3030+ if (ret)
3031+ goto err_disable_vreg;
3032+ udelay(10); /* no idea how long this should be? */
3033+ ret = gpio_direction_output(lp->pdata->reset, 1);
3034+ if (ret)
3035+ goto err_disable_vreg;
3036+ udelay(10);
3037+
3038+ ret = gpio_direction_input(lp->pdata->cca);
3039+ if (ret)
3040+ goto err_disable_vreg;
3041+ ret = gpio_direction_input(lp->pdata->fifo);
3042+ if (ret)
3043+ goto err_disable_vreg;
3044+ ret = gpio_direction_input(lp->pdata->fifop);
3045+ if (ret)
3046+ goto err_disable_vreg;
3047+ ret = gpio_direction_input(lp->pdata->sfd);
3048+ if (ret)
3049+ goto err_disable_vreg;
3050+
3051+
3052+ /* Check this is actually a cc2420 */
3053+ ret = cc2420_read_16_bit_reg(lp, CC2420_MANFIDL, &manidl);
3054+ if (ret)
3055+ goto err_free_gpio_vreg;
3056+ ret = cc2420_read_16_bit_reg(lp, CC2420_MANFIDH, &manidh);
3057+ if (ret)
3058+ goto err_free_gpio_vreg;
3059+ if (manidh != CC2420_MANFIDHIGH || manidl != CC2420_MANFIDLOW) {
3060+ dev_err(&spi->dev, "Incorrect manufacturer id %x%x\n", manidh, manidl);
3061+ ret = -ENODEV;
3062+ goto err_free_gpio_vreg;
3063+ }
3064+ /* TODO: make it more readable */
3065+ dev_info(&lp->spi->dev, "Found Chipcon CC2420\n");
3066+ dev_info(&lp->spi->dev, "Manufacturer ID:%x Version:%x Partnum:%x\n",
3067+ manidl & 0x0FFF, manidh >> 12, manidl >> 12);
3068+
3069+ ret = cc2420_hw_init(lp);
3070+ if (ret)
3071+ goto err_disable_vreg;
3072+
3073+ lp->fifop_irq = gpio_to_irq(lp->pdata->fifop);
3074+ lp->sfd_irq = gpio_to_irq(lp->pdata->sfd);
3075+
3076+ ret = request_irq(lp->fifop_irq,
3077+ cc2420_isr,
3078+ IRQF_TRIGGER_RISING | IRQF_SHARED,
3079+ dev_name(&spi->dev),
3080+ lp);
3081+ if (ret) {
3082+ dev_err(&spi->dev, "could not get fifop irq?\n");
3083+ goto err_free_fifop_irq;
3084+ }
3085+
3086+ ret = request_irq(lp->sfd_irq,
3087+ cc2420_isr,
3088+ IRQF_TRIGGER_FALLING,
3089+ dev_name(&spi->dev),
3090+ lp);
3091+ if (ret) {
3092+ dev_err(&spi->dev, "could not get sfd irq?\n");
3093+ goto err_free_sfd_irq;
3094+ }
3095+
3096+ dev_info(&lp->spi->dev, "Set fifo threshold to 127\n");
3097+ cc2420_write_16_bit_reg_partial(lp, CC2420_IOCFG0, 127, CC2420_FIFOP_THR_MASK);
3098+ ret = cc2420_register(lp);
3099+ if (ret)
3100+ goto err_free_sfd_irq;
3101+
3102+ return 0;
3103+err_free_sfd_irq:
3104+ free_irq(lp->sfd_irq, lp);
3105+err_free_fifop_irq:
3106+ free_irq(lp->fifop_irq, lp);
3107+err_disable_vreg:
3108+ gpio_set_value(lp->pdata->vreg, 0);
3109+err_free_gpio_vreg:
3110+ gpio_free(lp->pdata->vreg);
3111+err_free_gpio_reset:
3112+ gpio_free(lp->pdata->reset);
3113+err_free_gpio_sfd:
3114+ gpio_free(lp->pdata->sfd);
3115+err_free_gpio_fifop:
3116+ gpio_free(lp->pdata->fifop);
3117+//err_free_gpio_cca:
3118+// gpio_free(lp->pdata->cca);
3119+err_free_gpio_fifo:
3120+ gpio_free(lp->pdata->fifo);
3121+err_free_buf:
3122+ kfree(lp->buf);
3123+err_free_local:
3124+ kfree(lp);
3125+error_ret:
3126+ return ret;
3127+}
3128+
3129+static int __devexit cc2420_remove(struct spi_device *spi)
3130+{
3131+ struct cc2420_local *lp = spi_get_drvdata(spi);
3132+
3133+ cc2420_unregister(lp);
3134+ free_irq(lp->fifop_irq, lp);
3135+ free_irq(lp->sfd_irq, lp);
3136+ flush_work(&lp->fifop_irqwork);
3137+ flush_work(&lp->sfd_irqwork);
3138+ gpio_free(lp->pdata->vreg);
3139+ gpio_free(lp->pdata->reset);
3140+ gpio_free(lp->pdata->sfd);
3141+ gpio_free(lp->pdata->fifop);
3142+ gpio_free(lp->pdata->cca);
3143+ gpio_free(lp->pdata->fifo);
3144+ kfree(lp->buf);
3145+ kfree(lp);
3146+
3147+ return 0;
3148+}
3149+
3150+static struct spi_driver cc2420_driver = {
3151+ .driver = {
3152+ .name = "cc2420",
3153+ .owner = THIS_MODULE,
3154+ },
3155+ .probe = cc2420_probe,
3156+ .remove = __devexit_p(cc2420_remove),
3157+};
3158+
3159+static int __init cc2420_init(void)
3160+{
3161+ return spi_register_driver(&cc2420_driver);
3162+}
3163+module_init(cc2420_init);
3164+
3165+static void __exit cc2420_exit(void)
3166+{
3167+ spi_unregister_driver(&cc2420_driver);
3168+}
3169+module_exit(cc2420_exit);
3170+MODULE_LICENSE("GPL v2");
3171diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
3172index a5a49a1..1170074 100644
3173--- a/drivers/ieee802154/fakehard.c
3174@@ -259,7 +259,7 @@ static struct ieee802154_mlme_ops fake_mlme = {
3175     .start_req = fake_start_req,
3176     .scan_req = fake_scan_req,
3177
3178- .get_phy = fake_get_phy,
3179+ .wpan_ops.get_phy = fake_get_phy,
3180
3181     .get_pan_id = fake_get_pan_id,
3182     .get_short_addr = fake_get_short_addr,
3183@@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
3184         return -ENOMEM;
3185     }
3186
3187- phy->dev.platform_data = dev;
3188-
3189     memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
3190             dev->addr_len);
3191     memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
3192@@ -393,6 +391,16 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
3193     priv = netdev_priv(dev);
3194     priv->phy = phy;
3195
3196+ /*
3197+ * If the name is a format string the caller wants us to do a
3198+ * name allocation.
3199+ */
3200+ if (strchr(dev->name, '%')) {
3201+ err = dev_alloc_name(dev, dev->name);
3202+ if (err < 0)
3203+ goto out;
3204+ }
3205+
3206     wpan_phy_set_dev(phy, &pdev->dev);
3207     SET_NETDEV_DEV(dev, &phy->dev);
3208
3209diff --git a/drivers/ieee802154/fakelb.c b/drivers/ieee802154/fakelb.c
3210new file mode 100644
3211index 0000000..ae6e53f
3212--- /dev/null
3213@@ -0,0 +1,311 @@
3214+/*
3215+ * Loopback IEEE 802.15.4 interface
3216+ *
3217+ * Copyright 2007, 2008 Siemens AG
3218+ *
3219+ * This program is free software; you can redistribute it and/or modify
3220+ * it under the terms of the GNU General Public License version 2
3221+ * as published by the Free Software Foundation.
3222+ *
3223+ * This program is distributed in the hope that it will be useful,
3224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3226+ * GNU General Public License for more details.
3227+ *
3228+ * You should have received a copy of the GNU General Public License along
3229+ * with this program; if not, write to the Free Software Foundation, Inc.,
3230+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3231+ *
3232+ * Written by:
3233+ * Sergey Lapin <slapin@ossfans.org>
3234+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
3235+ */
3236+
3237+#include <linux/module.h>
3238+#include <linux/timer.h>
3239+#include <linux/platform_device.h>
3240+#include <linux/netdevice.h>
3241+#include <linux/spinlock.h>
3242+#include <net/mac802154.h>
3243+#include <net/wpan-phy.h>
3244+
3245+struct fake_dev_priv {
3246+ struct ieee802154_dev *dev;
3247+
3248+ struct list_head list;
3249+ struct fake_priv *fake;
3250+
3251+ unsigned int working:1;
3252+};
3253+
3254+struct fake_priv {
3255+ struct list_head list;
3256+ rwlock_t lock;
3257+};
3258+
3259+static int
3260+hw_ed(struct ieee802154_dev *dev, u8 *level)
3261+{
3262+ pr_debug("%s\n", __func__);
3263+ might_sleep();
3264+ BUG_ON(!level);
3265+ *level = 0xbe;
3266+ return 0;
3267+}
3268+
3269+static int
3270+hw_channel(struct ieee802154_dev *dev, int page, int channel)
3271+{
3272+ pr_debug("%s %d\n", __func__, channel);
3273+ might_sleep();
3274+ dev->phy->current_page = page;
3275+ dev->phy->current_channel = channel;
3276+ return 0;
3277+}
3278+
3279+static void
3280+hw_deliver(struct fake_dev_priv *priv, struct sk_buff *skb)
3281+{
3282+ struct sk_buff *newskb;
3283+
3284+ if (!priv->working)
3285+ return;
3286+
3287+ newskb = pskb_copy(skb, GFP_ATOMIC);
3288+
3289+ ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
3290+}
3291+
3292+static int
3293+hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
3294+{
3295+ struct fake_dev_priv *priv = dev->priv;
3296+ struct fake_priv *fake = priv->fake;
3297+
3298+ might_sleep();
3299+
3300+ read_lock_bh(&fake->lock);
3301+ if (priv->list.next == priv->list.prev) {
3302+ /* we are the only one device */
3303+ hw_deliver(priv, skb);
3304+ } else {
3305+ struct fake_dev_priv *dp;
3306+ list_for_each_entry(dp, &priv->fake->list, list)
3307+ if (dp != priv &&
3308+ dp->dev->phy->current_channel ==
3309+ priv->dev->phy->current_channel)
3310+ hw_deliver(dp, skb);
3311+ }
3312+ read_unlock_bh(&fake->lock);
3313+
3314+ return 0;
3315+}
3316+
3317+static int
3318+hw_start(struct ieee802154_dev *dev) {
3319+ struct fake_dev_priv *priv = dev->priv;
3320+
3321+ if (priv->working)
3322+ return -EBUSY;
3323+
3324+ priv->working = 1;
3325+
3326+ return 0;
3327+}
3328+
3329+static void
3330+hw_stop(struct ieee802154_dev *dev) {
3331+ struct fake_dev_priv *priv = dev->priv;
3332+
3333+ priv->working = 0;
3334+}
3335+
3336+static struct ieee802154_ops fake_ops = {
3337+ .owner = THIS_MODULE,
3338+ .xmit = hw_xmit,
3339+ .ed = hw_ed,
3340+ .set_channel = hw_channel,
3341+ .start = hw_start,
3342+ .stop = hw_stop,
3343+};
3344+
3345+static int ieee802154fake_add_priv(struct device *dev, struct fake_priv *fake)
3346+{
3347+ struct fake_dev_priv *priv;
3348+ int err = -ENOMEM;
3349+ struct ieee802154_dev *ieee;
3350+
3351+ ieee = ieee802154_alloc_device(sizeof(*priv), &fake_ops);
3352+ if (!dev)
3353+ goto err_alloc_dev;
3354+
3355+ priv = ieee->priv;
3356+ priv->dev = ieee;
3357+
3358+ /* 868 MHz BPSK 802.15.4-2003 */
3359+ ieee->phy->channels_supported[0] |= 1;
3360+ /* 915 MHz BPSK 802.15.4-2003 */
3361+ ieee->phy->channels_supported[0] |= 0x7fe;
3362+ /* 2.4 GHz O-QPSK 802.15.4-2003 */
3363+ ieee->phy->channels_supported[0] |= 0x7FFF800;
3364+ /* 868 MHz ASK 802.15.4-2006 */
3365+ ieee->phy->channels_supported[1] |= 1;
3366+ /* 915 MHz ASK 802.15.4-2006 */
3367+ ieee->phy->channels_supported[1] |= 0x7fe;
3368+ /* 868 MHz O-QPSK 802.15.4-2006 */
3369+ ieee->phy->channels_supported[2] |= 1;
3370+ /* 915 MHz O-QPSK 802.15.4-2006 */
3371+ ieee->phy->channels_supported[2] |= 0x7fe;
3372+ /* 2.4 GHz CSS 802.15.4a-2007 */
3373+ ieee->phy->channels_supported[3] |= 0x3fff;
3374+ /* UWB Sub-gigahertz 802.15.4a-2007 */
3375+ ieee->phy->channels_supported[4] |= 1;
3376+ /* UWB Low band 802.15.4a-2007 */
3377+ ieee->phy->channels_supported[4] |= 0x1e;
3378+ /* UWB High band 802.15.4a-2007 */
3379+ ieee->phy->channels_supported[4] |= 0xffe0;
3380+ /* 750 MHz O-QPSK 802.15.4c-2009 */
3381+ ieee->phy->channels_supported[5] |= 0xf;
3382+ /* 750 MHz MPSK 802.15.4c-2009 */
3383+ ieee->phy->channels_supported[5] |= 0xf0;
3384+ /* 950 MHz BPSK 802.15.4d-2009 */
3385+ ieee->phy->channels_supported[6] |= 0x3ff;
3386+ /* 950 MHz GFSK 802.15.4d-2009 */
3387+ ieee->phy->channels_supported[6] |= 0x3ffc00;
3388+
3389+
3390+ INIT_LIST_HEAD(&priv->list);
3391+ priv->fake = fake;
3392+
3393+ ieee->parent = dev;
3394+
3395+ err = ieee802154_register_device(ieee);
3396+ if (err)
3397+ goto err_reg;
3398+
3399+ write_lock_bh(&fake->lock);
3400+ list_add_tail(&priv->list, &fake->list);
3401+ write_unlock_bh(&fake->lock);
3402+
3403+ return 0;
3404+
3405+err_reg:
3406+ ieee802154_free_device(priv->dev);
3407+err_alloc_dev:
3408+ return err;
3409+}
3410+
3411+static void ieee802154fake_del_priv(struct fake_dev_priv *priv)
3412+{
3413+ write_lock_bh(&priv->fake->lock);
3414+ list_del(&priv->list);
3415+ write_unlock_bh(&priv->fake->lock);
3416+
3417+ ieee802154_unregister_device(priv->dev);
3418+ ieee802154_free_device(priv->dev);
3419+}
3420+
3421+static ssize_t
3422+adddev_store(struct device *dev, struct device_attribute *attr,
3423+ const char *buf, size_t n)
3424+{
3425+ struct platform_device *pdev = to_platform_device(dev);
3426+ struct fake_priv *priv = platform_get_drvdata(pdev);
3427+ int err;
3428+
3429+ err = ieee802154fake_add_priv(dev, priv);
3430+ if (err)
3431+ return err;
3432+ return n;
3433+}
3434+
3435+static DEVICE_ATTR(adddev, 0200, NULL, adddev_store);
3436+
3437+static struct attribute *fake_attrs[] = {
3438+ &dev_attr_adddev.attr,
3439+ NULL,
3440+};
3441+
3442+static struct attribute_group fake_group = {
3443+ .name = NULL /* fake */,
3444+ .attrs = fake_attrs,
3445+};
3446+
3447+
3448+static int __devinit ieee802154fake_probe(struct platform_device *pdev)
3449+{
3450+ struct fake_priv *priv;
3451+ struct fake_dev_priv *dp;
3452+
3453+ int err = -ENOMEM;
3454+ priv = kzalloc(sizeof(struct fake_priv), GFP_KERNEL);
3455+ if (!priv)
3456+ goto err_alloc;
3457+
3458+ INIT_LIST_HEAD(&priv->list);
3459+ rwlock_init(&priv->lock);
3460+
3461+ err = sysfs_create_group(&pdev->dev.kobj, &fake_group);
3462+ if (err)
3463+ goto err_grp;
3464+
3465+ err = ieee802154fake_add_priv(&pdev->dev, priv);
3466+ if (err < 0)
3467+ goto err_slave;
3468+
3469+ platform_set_drvdata(pdev, priv);
3470+ dev_info(&pdev->dev, "Added ieee802154 hardware\n");
3471+ return 0;
3472+
3473+err_slave:
3474+ list_for_each_entry(dp, &priv->list, list)
3475+ ieee802154fake_del_priv(dp);
3476+ sysfs_remove_group(&pdev->dev.kobj, &fake_group);
3477+err_grp:
3478+ kfree(priv);
3479+err_alloc:
3480+ return err;
3481+}
3482+
3483+static int __devexit ieee802154fake_remove(struct platform_device *pdev)
3484+{
3485+ struct fake_priv *priv = platform_get_drvdata(pdev);
3486+ struct fake_dev_priv *dp, *temp;
3487+
3488+ list_for_each_entry_safe(dp, temp, &priv->list, list)
3489+ ieee802154fake_del_priv(dp);
3490+ sysfs_remove_group(&pdev->dev.kobj, &fake_group);
3491+ kfree(priv);
3492+ return 0;
3493+}
3494+
3495+static struct platform_device *ieee802154fake_dev;
3496+
3497+static struct platform_driver ieee802154fake_driver = {
3498+ .probe = ieee802154fake_probe,
3499+ .remove = __devexit_p(ieee802154fake_remove),
3500+ .driver = {
3501+ .name = "ieee802154fakelb",
3502+ .owner = THIS_MODULE,
3503+ },
3504+};
3505+
3506+static __init int fake_init(void)
3507+{
3508+ ieee802154fake_dev = platform_device_register_simple(
3509+ "ieee802154fakelb", -1, NULL, 0);
3510+ return platform_driver_register(&ieee802154fake_driver);
3511+}
3512+
3513+static __exit void fake_exit(void)
3514+{
3515+ platform_driver_unregister(&ieee802154fake_driver);
3516+ platform_device_unregister(ieee802154fake_dev);
3517+}
3518+
3519+module_init(fake_init);
3520+module_exit(fake_exit);
3521+MODULE_LICENSE("GPL");
3522+MODULE_AUTHOR("Dmitry Eremin-Solenikov, Sergey Lapin");
3523+
3524+
3525diff --git a/drivers/ieee802154/serial.c b/drivers/ieee802154/serial.c
3526new file mode 100644
3527index 0000000..6981d0e
3528--- /dev/null
3529@@ -0,0 +1,1047 @@
3530+/*
3531+ * ZigBee TTY line discipline.
3532+ *
3533+ * Provides interface between ZigBee stack and IEEE 802.15.4 compatible
3534+ * firmware over serial line. Communication protocol is described below.
3535+ *
3536+ * Copyright (C) 2007, 2008, 2009 Siemens AG
3537+ *
3538+ * This program is free software; you can redistribute it and/or modify
3539+ * it under the terms of the GNU General Public License version 2
3540+ * as published by the Free Software Foundation.
3541+ *
3542+ * This program is distributed in the hope that it will be useful,
3543+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3544+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3545+ * GNU General Public License for more details.
3546+ *
3547+ * You should have received a copy of the GNU General Public License along
3548+ * with this program; if not, write to the Free Software Foundation, Inc.,
3549+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3550+ *
3551+ * Written by:
3552+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
3553+ * Maxim Osipov <maxim.osipov@siemens.com>
3554+ * Sergey Lapin <slapin@ossfans.org>
3555+ */
3556+
3557+#include <linux/module.h>
3558+#include <linux/kernel.h>
3559+#include <linux/completion.h>
3560+#include <linux/tty.h>
3561+#include <linux/skbuff.h>
3562+#include <linux/sched.h>
3563+#include <net/mac802154.h>
3564+#include <net/wpan-phy.h>
3565+
3566+
3567+/* NOTE: be sure to use here the same values as in the firmware */
3568+#define START_BYTE1 'z'
3569+#define START_BYTE2 'b'
3570+#define MAX_DATA_SIZE 127
3571+
3572+#define IDLE_MODE 0x00
3573+#define RX_MODE 0x02
3574+#define TX_MODE 0x03
3575+#define FORCE_TRX_OFF 0xF0
3576+
3577+#define STATUS_SUCCESS 0
3578+#define STATUS_RX_ON 1
3579+#define STATUS_TX_ON 2
3580+#define STATUS_TRX_OFF 3
3581+#define STATUS_IDLE 4
3582+#define STATUS_BUSY 5
3583+#define STATUS_BUSY_RX 6
3584+#define STATUS_BUSY_TX 7
3585+#define STATUS_ERR 8
3586+
3587+#define STATUS_WAIT ((u8) -1) /* waiting for the answer */
3588+
3589+/* We re-use PPP ioctl for our purposes */
3590+#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
3591+
3592+/*
3593+ * The following messages are used to control ZigBee firmware.
3594+ * All communication has request/response format,
3595+ * except of asynchronous incoming data stream (DATA_RECV_* messages).
3596+ */
3597+enum {
3598+ NO_ID = 0, /* means no pending id */
3599+
3600+ /* Driver to Firmware */
3601+ CMD_OPEN = 0x01, /* u8 id */
3602+ CMD_CLOSE = 0x02, /* u8 id */
3603+ CMD_SET_CHANNEL = 0x04, /* u8 id, u8 channel */
3604+ CMD_ED = 0x05, /* u8 id */
3605+ CMD_CCA = 0x06, /* u8 id */
3606+ CMD_SET_STATE = 0x07, /* u8 id, u8 flag */
3607+ DATA_XMIT_BLOCK = 0x09, /* u8 id, u8 len, u8 data[len] */
3608+ RESP_RECV_BLOCK = 0x0b, /* u8 id, u8 status */
3609+ CMD_ADDRESS = 0x0d, /* u8 id */
3610+
3611+ /* Firmware to Driver */
3612+ RESP_OPEN = 0x81, /* u8 id, u8 status */
3613+ RESP_CLOSE = 0x82, /* u8 id, u8 status */
3614+ RESP_SET_CHANNEL = 0x84, /* u8 id, u8 status */
3615+ RESP_ED = 0x85, /* u8 id, u8 status, u8 level */
3616+ RESP_CCA = 0x86, /* u8 id, u8 status */
3617+ RESP_SET_STATE = 0x87, /* u8 id, u8 status */
3618+ RESP_XMIT_BLOCK = 0x89, /* u8 id, u8 status */
3619+ DATA_RECV_BLOCK = 0x8b, /* u8 id, u8 lq, u8 len, u8 data[len] */
3620+ RESP_ADDRESS = 0x8d, /* u8 id, u8 status, u8 u8 u8 u8 u8 u8 u8 u8 address */
3621+};
3622+
3623+enum {
3624+ STATE_WAIT_START1,
3625+ STATE_WAIT_START2,
3626+ STATE_WAIT_COMMAND,
3627+ STATE_WAIT_PARAM1,
3628+ STATE_WAIT_PARAM2,
3629+ STATE_WAIT_DATA
3630+};
3631+
3632+struct zb_device {
3633+ /* Relative devices */
3634+ struct tty_struct *tty;
3635+ struct ieee802154_dev *dev;
3636+
3637+ /* locks the ldisc for the command */
3638+ struct mutex mutex;
3639+
3640+ /* command completition */
3641+ wait_queue_head_t wq;
3642+ u8 status;
3643+ u8 ed;
3644+
3645+ /* Internal state */
3646+ struct completion open_done;
3647+ unsigned char opened;
3648+ u8 pending_id;
3649+ unsigned int pending_size;
3650+ u8 *pending_data;
3651+ /* FIXME: WE NEED LOCKING!!! */
3652+
3653+ /* Command (rx) processing */
3654+ int state;
3655+ unsigned char id;
3656+ unsigned char param1;
3657+ unsigned char param2;
3658+ unsigned char index;
3659+ unsigned char data[MAX_DATA_SIZE];
3660+};
3661+
3662+/*****************************************************************************
3663+ * ZigBee serial device protocol handling
3664+ *****************************************************************************/
3665+static int _open_dev(struct zb_device *zbdev);
3666+
3667+static int
3668+_send_pending_data(struct zb_device *zbdev)
3669+{
3670+ struct tty_struct *tty;
3671+
3672+ BUG_ON(!zbdev);
3673+ tty = zbdev->tty;
3674+ if (!tty)
3675+ return -ENODEV;
3676+
3677+ zbdev->status = STATUS_WAIT;
3678+
3679+ /* Debug info */
3680+ printk(KERN_INFO "%s, %d bytes\n", __func__,
3681+ zbdev->pending_size);
3682+#ifdef DEBUG
3683+ print_hex_dump_bytes("send_pending_data ", DUMP_PREFIX_NONE,
3684+ zbdev->pending_data, zbdev->pending_size);
3685+#endif
3686+
3687+ if (tty->driver->ops->write(tty, zbdev->pending_data,
3688+ zbdev->pending_size) != zbdev->pending_size) {
3689+ printk(KERN_ERR "%s: device write failed\n", __func__);
3690+ return -1;
3691+ }
3692+
3693+ return 0;
3694+}
3695+
3696+static int
3697+send_cmd(struct zb_device *zbdev, u8 id)
3698+{
3699+ u8 len = 0;
3700+ /* 4 because of 2 start bytes, id and optional extra */
3701+ u8 buf[4];
3702+
3703+ /* Check arguments */
3704+ BUG_ON(!zbdev);
3705+
3706+ if (!zbdev->opened) {
3707+ if (!_open_dev(zbdev))
3708+ return -EAGAIN;
3709+ }
3710+
3711+ pr_debug("%s(): id = %u\n", __func__, id);
3712+ if (zbdev->pending_size) {
3713+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3714+ __func__, zbdev->pending_id);
3715+ BUG();
3716+ }
3717+
3718+ /* Prepare a message */
3719+ buf[len++] = START_BYTE1;
3720+ buf[len++] = START_BYTE2;
3721+ buf[len++] = id;
3722+
3723+ zbdev->pending_id = id;
3724+ zbdev->pending_size = len;
3725+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3726+ if (!zbdev->pending_data) {
3727+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3728+ zbdev->pending_id = 0;
3729+ zbdev->pending_size = 0;
3730+ return -ENOMEM;
3731+ }
3732+ memcpy(zbdev->pending_data, buf, len);
3733+
3734+ return _send_pending_data(zbdev);
3735+}
3736+
3737+static int
3738+send_cmd2(struct zb_device *zbdev, u8 id, u8 extra)
3739+{
3740+ u8 len = 0;
3741+ /* 4 because of 2 start bytes, id and optional extra */
3742+ u8 buf[4];
3743+
3744+ /* Check arguments */
3745+ BUG_ON(!zbdev);
3746+
3747+ if (!zbdev->opened) {
3748+ if (!_open_dev(zbdev))
3749+ return -EAGAIN;
3750+ }
3751+
3752+ pr_debug("%s(): id = %u\n", __func__, id);
3753+ if (zbdev->pending_size) {
3754+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3755+ __func__, zbdev->pending_id);
3756+ BUG();
3757+ }
3758+
3759+ /* Prepare a message */
3760+ buf[len++] = START_BYTE1;
3761+ buf[len++] = START_BYTE2;
3762+ buf[len++] = id;
3763+ buf[len++] = extra;
3764+
3765+ zbdev->pending_id = id;
3766+ zbdev->pending_size = len;
3767+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3768+ if (!zbdev->pending_data) {
3769+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3770+ zbdev->pending_id = 0;
3771+ zbdev->pending_size = 0;
3772+ return -ENOMEM;
3773+ }
3774+ memcpy(zbdev->pending_data, buf, len);
3775+
3776+ return _send_pending_data(zbdev);
3777+}
3778+
3779+static int
3780+send_block(struct zb_device *zbdev, u8 len, u8 *data)
3781+{
3782+ u8 i = 0, buf[4]; /* 4 because of 2 start bytes, id and len */
3783+
3784+ /* Check arguments */
3785+ BUG_ON(!zbdev);
3786+
3787+ if (!zbdev->opened) {
3788+ if (!_open_dev(zbdev))
3789+ return -EAGAIN;
3790+ }
3791+
3792+ pr_debug("%s(): id = %u\n", __func__, DATA_XMIT_BLOCK);
3793+ if (zbdev->pending_size) {
3794+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3795+ __func__, zbdev->pending_id);
3796+ BUG();
3797+ }
3798+
3799+ /* Prepare a message */
3800+ buf[i++] = START_BYTE1;
3801+ buf[i++] = START_BYTE2;
3802+ buf[i++] = DATA_XMIT_BLOCK;
3803+ buf[i++] = len;
3804+
3805+ zbdev->pending_id = DATA_XMIT_BLOCK;
3806+ zbdev->pending_size = i + len;
3807+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3808+ if (!zbdev->pending_data) {
3809+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3810+ zbdev->pending_id = 0;
3811+ zbdev->pending_size = 0;
3812+ return -ENOMEM;
3813+ }
3814+ memcpy(zbdev->pending_data, buf, i);
3815+ memcpy(zbdev->pending_data + i, data, len);
3816+
3817+ return _send_pending_data(zbdev);
3818+}
3819+
3820+static void
3821+cleanup(struct zb_device *zbdev)
3822+{
3823+ zbdev->state = STATE_WAIT_START1;
3824+ zbdev->id = 0;
3825+ zbdev->param1 = 0;
3826+ zbdev->param2 = 0;
3827+ zbdev->index = 0;
3828+}
3829+
3830+static int
3831+is_command(unsigned char c)
3832+{
3833+ switch (c) {
3834+ /* ids we can get here: */
3835+ case RESP_OPEN:
3836+ case RESP_CLOSE:
3837+ case RESP_SET_CHANNEL:
3838+ case RESP_ED:
3839+ case RESP_CCA:
3840+ case RESP_SET_STATE:
3841+ case RESP_XMIT_BLOCK:
3842+ case DATA_RECV_BLOCK:
3843+ case RESP_ADDRESS:
3844+ return 1;
3845+ }
3846+ return 0;
3847+}
3848+
3849+static int
3850+_match_pending_id(struct zb_device *zbdev)
3851+{
3852+ return ((CMD_OPEN == zbdev->pending_id &&
3853+ RESP_OPEN == zbdev->id) ||
3854+ (CMD_CLOSE == zbdev->pending_id &&
3855+ RESP_CLOSE == zbdev->id) ||
3856+ (CMD_SET_CHANNEL == zbdev->pending_id &&
3857+ RESP_SET_CHANNEL == zbdev->id) ||
3858+ (CMD_ED == zbdev->pending_id &&
3859+ RESP_ED == zbdev->id) ||
3860+ (CMD_CCA == zbdev->pending_id &&
3861+ RESP_CCA == zbdev->id) ||
3862+ (CMD_SET_STATE == zbdev->pending_id &&
3863+ RESP_SET_STATE == zbdev->id) ||
3864+ (DATA_XMIT_BLOCK == zbdev->pending_id &&
3865+ RESP_XMIT_BLOCK == zbdev->id) ||
3866+ (DATA_RECV_BLOCK == zbdev->id) ||
3867+ (CMD_ADDRESS == zbdev->pending_id &&
3868+ RESP_ADDRESS == zbdev->id));
3869+}
3870+
3871+static void serial_net_rx(struct zb_device *zbdev)
3872+{
3873+ /* zbdev->param1 is LQI
3874+ * zbdev->param2 is length of data
3875+ * zbdev->data is data itself
3876+ */
3877+ struct sk_buff *skb;
3878+ skb = alloc_skb(zbdev->param2, GFP_ATOMIC);
3879+ skb_put(skb, zbdev->param2);
3880+ skb_copy_to_linear_data(skb, zbdev->data, zbdev->param2);
3881+ ieee802154_rx_irqsafe(zbdev->dev, skb, zbdev->param1);
3882+}
3883+
3884+static void
3885+process_command(struct zb_device *zbdev)
3886+{
3887+ /* Command processing */
3888+ if (!_match_pending_id(zbdev))
3889+ return;
3890+
3891+ if (RESP_OPEN == zbdev->id && STATUS_SUCCESS == zbdev->param1) {
3892+ zbdev->opened = 1;
3893+ pr_debug("Opened device\n");
3894+ complete(&zbdev->open_done);
3895+ /* Input is not processed during output, so
3896+ * using completion is not possible during output.
3897+ * so we need to handle open as any other command
3898+ * and hope for best
3899+ */
3900+ return;
3901+ }
3902+
3903+ if (!zbdev->opened)
3904+ return;
3905+
3906+ zbdev->pending_id = 0;
3907+ kfree(zbdev->pending_data);
3908+ zbdev->pending_data = NULL;
3909+ zbdev->pending_size = 0;
3910+ if (zbdev->id != DATA_RECV_BLOCK) {
3911+ /* XXX: w/around for old FW, REMOVE */
3912+ if (zbdev->param1 == STATUS_IDLE)
3913+ zbdev->status = STATUS_SUCCESS;
3914+ else
3915+ zbdev->status = zbdev->param1;
3916+ }
3917+
3918+ switch (zbdev->id) {
3919+ case RESP_ED:
3920+ zbdev->ed = zbdev->param2;
3921+ break;
3922+ case DATA_RECV_BLOCK:
3923+ pr_debug("Received block, lqi %02x, len %02x\n",
3924+ zbdev->param1, zbdev->param2);
3925+ /* zbdev->param1 is LQ, zbdev->param2 is length */
3926+ serial_net_rx(zbdev);
3927+ break;
3928+ case RESP_ADDRESS:
3929+ pr_debug("Received address, %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3930+ zbdev->data[0], zbdev->data[1], zbdev->data[2], zbdev->data[3],
3931+ zbdev->data[4], zbdev->data[5], zbdev->data[6], zbdev->data[7]);
3932+ break;
3933+ }
3934+
3935+ wake_up(&zbdev->wq);
3936+}
3937+
3938+static void
3939+process_char(struct zb_device *zbdev, unsigned char c)
3940+{
3941+ /* Data processing */
3942+ switch (zbdev->state) {
3943+ case STATE_WAIT_START1:
3944+ if (START_BYTE1 == c)
3945+ zbdev->state = STATE_WAIT_START2;
3946+ break;
3947+
3948+ case STATE_WAIT_START2:
3949+ if (START_BYTE2 == c)
3950+ zbdev->state = STATE_WAIT_COMMAND;
3951+ else
3952+ cleanup(zbdev);
3953+ break;
3954+
3955+ case STATE_WAIT_COMMAND:
3956+ if (is_command(c)) {
3957+ zbdev->id = c;
3958+ zbdev->state = STATE_WAIT_PARAM1;
3959+ } else {
3960+ cleanup(zbdev);
3961+ printk(KERN_ERR "%s, unexpected command id: %x\n",
3962+ __func__, c);
3963+ }
3964+ break;
3965+
3966+ case STATE_WAIT_PARAM1:
3967+ zbdev->param1 = c;
3968+ if ((RESP_ED == zbdev->id) || (DATA_RECV_BLOCK == zbdev->id))
3969+ zbdev->state = STATE_WAIT_PARAM2;
3970+ else if (RESP_ADDRESS == zbdev->id) {
3971+ zbdev->param2 = 8;
3972+ zbdev->state = STATE_WAIT_DATA;
3973+ } else {
3974+ process_command(zbdev);
3975+ cleanup(zbdev);
3976+ }
3977+ break;
3978+
3979+ case STATE_WAIT_PARAM2:
3980+ zbdev->param2 = c;
3981+ if (RESP_ED == zbdev->id) {
3982+ process_command(zbdev);
3983+ cleanup(zbdev);
3984+ } else if (DATA_RECV_BLOCK == zbdev->id)
3985+ zbdev->state = STATE_WAIT_DATA;
3986+ else
3987+ cleanup(zbdev);
3988+ break;
3989+
3990+ case STATE_WAIT_DATA:
3991+ if (zbdev->index < sizeof(zbdev->data)) {
3992+ zbdev->data[zbdev->index] = c;
3993+ zbdev->index++;
3994+ /*
3995+ * Pending data is received,
3996+ * param2 is length for DATA_RECV_BLOCK
3997+ */
3998+ if (zbdev->index == zbdev->param2) {
3999+ process_command(zbdev);
4000+ cleanup(zbdev);
4001+ }
4002+ } else {
4003+ printk(KERN_ERR "%s(): data size is greater "
4004+ "than buffer available\n", __func__);
4005+ cleanup(zbdev);
4006+ }
4007+ break;
4008+
4009+ default:
4010+ cleanup(zbdev);
4011+ }
4012+}
4013+
4014+/*****************************************************************************
4015+ * Device operations for IEEE 802.15.4 PHY side interface ZigBee stack
4016+ *****************************************************************************/
4017+
4018+static int _open_dev(struct zb_device *zbdev)
4019+{
4020+ int retries;
4021+ u8 len = 0;
4022+ /* 4 because of 2 start bytes, id and optional extra */
4023+ u8 buf[4];
4024+
4025+ /* Check arguments */
4026+ BUG_ON(!zbdev);
4027+ if (zbdev->opened)
4028+ return 1;
4029+
4030+ pr_debug("%s()\n", __func__);
4031+ if (zbdev->pending_size) {
4032+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
4033+ __func__, zbdev->pending_id);
4034+ BUG();
4035+ }
4036+
4037+ /* Prepare a message */
4038+ buf[len++] = START_BYTE1;
4039+ buf[len++] = START_BYTE2;
4040+ buf[len++] = CMD_OPEN;
4041+
4042+ zbdev->pending_id = CMD_OPEN;
4043+ zbdev->pending_size = len;
4044+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
4045+ if (!zbdev->pending_data) {
4046+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
4047+ zbdev->pending_id = 0;
4048+ zbdev->pending_size = 0;
4049+ return -ENOMEM;
4050+ }
4051+ memcpy(zbdev->pending_data, buf, len);
4052+
4053+ retries = 5;
4054+ while (!zbdev->opened && retries) {
4055+ if (_send_pending_data(zbdev) != 0)
4056+ return 0;
4057+
4058+ /* 3 second before retransmission */
4059+ wait_for_completion_interruptible_timeout(
4060+ &zbdev->open_done, msecs_to_jiffies(1000));
4061+ --retries;
4062+ }
4063+
4064+ zbdev->pending_id = 0;
4065+ kfree(zbdev->pending_data);
4066+ zbdev->pending_data = NULL;
4067+ zbdev->pending_size = 0;
4068+
4069+ if (zbdev->opened) {
4070+ printk(KERN_INFO "Opened connection to device\n");
4071+ return 1;
4072+ }
4073+
4074+ return 0;
4075+}
4076+
4077+/* Valid channels: 1-16 */
4078+static int
4079+ieee802154_serial_set_channel(struct ieee802154_dev *dev, int page, int channel)
4080+{
4081+ struct zb_device *zbdev;
4082+ int ret = 0;
4083+
4084+ pr_debug("%s %d\n", __func__, channel);
4085+
4086+ zbdev = dev->priv;
4087+ if (NULL == zbdev) {
4088+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4089+ return -EINVAL;
4090+ }
4091+
4092+ BUG_ON(page != 0);
4093+ /* Our channels are actually from 11 to 26
4094+ * We have IEEE802.15.4 channel no from 0 to 26.
4095+ * channels 0-10 are not valid for us */
4096+ BUG_ON(channel < 11 || channel > 26);
4097+ /* ... but our crappy firmware numbers channels from 1 to 16
4098+ * which is a mystery. We suould enforce that using PIB API
4099+ * but additional checking here won't kill, and gcc will
4100+ * optimize this stuff anyway. */
4101+ BUG_ON((channel - 10) < 1 && (channel - 10) > 16);
4102+ if (mutex_lock_interruptible(&zbdev->mutex))
4103+ return -EINTR;
4104+ ret = send_cmd2(zbdev, CMD_SET_CHANNEL, channel - 10);
4105+ if (ret)
4106+ goto out;
4107+
4108+ if (wait_event_interruptible_timeout(zbdev->wq,
4109+ zbdev->status != STATUS_WAIT,
4110+ msecs_to_jiffies(1000)) > 0) {
4111+ if (zbdev->status != STATUS_SUCCESS)
4112+ ret = -EBUSY;
4113+ } else
4114+ ret = -EINTR;
4115+
4116+ if (!ret)
4117+ zbdev->dev->phy->current_channel = channel;
4118+out:
4119+ mutex_unlock(&zbdev->mutex);
4120+ pr_debug("%s end\n", __func__);
4121+ return ret;
4122+}
4123+
4124+static int
4125+ieee802154_serial_ed(struct ieee802154_dev *dev, u8 *level)
4126+{
4127+ struct zb_device *zbdev;
4128+ int ret = 0;
4129+
4130+ pr_debug("%s\n", __func__);
4131+
4132+ zbdev = dev->priv;
4133+ if (NULL == zbdev) {
4134+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4135+ return -EINVAL;
4136+ }
4137+
4138+ if (mutex_lock_interruptible(&zbdev->mutex))
4139+ return -EINTR;
4140+
4141+ ret = send_cmd(zbdev, CMD_ED);
4142+ if (ret)
4143+ goto out;
4144+
4145+ if (wait_event_interruptible_timeout(zbdev->wq,
4146+ zbdev->status != STATUS_WAIT,
4147+ msecs_to_jiffies(1000)) > 0) {
4148+ *level = zbdev->ed;
4149+ if (zbdev->status != STATUS_SUCCESS)
4150+ ret = -EBUSY;
4151+ } else
4152+ ret = -ETIMEDOUT;
4153+out:
4154+
4155+ mutex_unlock(&zbdev->mutex);
4156+ pr_debug("%s end\n", __func__);
4157+ return ret;
4158+}
4159+
4160+static int
4161+ieee802154_serial_address(struct ieee802154_dev *dev, u8 addr[IEEE802154_ALEN])
4162+{
4163+ struct zb_device *zbdev;
4164+ int ret = 0;
4165+
4166+ pr_debug("%s\n", __func__);
4167+
4168+ zbdev = dev->priv;
4169+ if (NULL == zbdev) {
4170+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4171+ return -EINVAL;
4172+ }
4173+
4174+ if (mutex_lock_interruptible(&zbdev->mutex))
4175+ return -EINTR;
4176+
4177+ ret = send_cmd(zbdev, CMD_ADDRESS);
4178+ if (ret)
4179+ goto out;
4180+
4181+ if (wait_event_interruptible_timeout(zbdev->wq,
4182+ zbdev->status != STATUS_WAIT,
4183+ msecs_to_jiffies(1000)) > 0) {
4184+ memcpy(addr, zbdev->data, sizeof addr);
4185+ if (zbdev->status != STATUS_SUCCESS)
4186+ ret = -EBUSY;
4187+ } else
4188+ ret = -ETIMEDOUT;
4189+out:
4190+
4191+ mutex_unlock(&zbdev->mutex);
4192+ pr_debug("%s end\n", __func__);
4193+ return ret;
4194+}
4195+
4196+static int
4197+ieee802154_serial_start(struct ieee802154_dev *dev)
4198+{
4199+ struct zb_device *zbdev;
4200+ int ret = 0;
4201+
4202+ pr_debug("%s\n", __func__);
4203+
4204+ zbdev = dev->priv;
4205+ if (NULL == zbdev) {
4206+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4207+ return -EINVAL;
4208+ }
4209+
4210+ if (mutex_lock_interruptible(&zbdev->mutex))
4211+ return -EINTR;
4212+
4213+ ret = send_cmd2(zbdev, CMD_SET_STATE, RX_MODE);
4214+ if (ret)
4215+ goto out;
4216+
4217+ if (wait_event_interruptible_timeout(zbdev->wq,
4218+ zbdev->status != STATUS_WAIT,
4219+ msecs_to_jiffies(1000)) > 0) {
4220+ if (zbdev->status != STATUS_SUCCESS)
4221+ ret = -EBUSY;
4222+ } else
4223+ ret = -ETIMEDOUT;
4224+out:
4225+ mutex_unlock(&zbdev->mutex);
4226+ pr_debug("%s end\n", __func__);
4227+ return ret;
4228+}
4229+
4230+static void
4231+ieee802154_serial_stop(struct ieee802154_dev *dev)
4232+{
4233+ struct zb_device *zbdev;
4234+ pr_debug("%s\n", __func__);
4235+
4236+ zbdev = dev->priv;
4237+ if (NULL == zbdev) {
4238+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4239+ return;
4240+ }
4241+
4242+ if (mutex_lock_interruptible(&zbdev->mutex))
4243+ return;
4244+
4245+
4246+ if (send_cmd2(zbdev, CMD_SET_STATE, FORCE_TRX_OFF) != 0)
4247+ goto out;
4248+
4249+ wait_event_interruptible_timeout(zbdev->wq,
4250+ zbdev->status != STATUS_WAIT,
4251+ msecs_to_jiffies(1000));
4252+out:
4253+ mutex_unlock(&zbdev->mutex);
4254+ pr_debug("%s end\n", __func__);
4255+}
4256+
4257+static int
4258+ieee802154_serial_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
4259+{
4260+ struct zb_device *zbdev;
4261+ int ret;
4262+
4263+ pr_debug("%s\n", __func__);
4264+
4265+ zbdev = dev->priv;
4266+ if (NULL == zbdev) {
4267+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4268+ return -EINVAL;
4269+ }
4270+
4271+ if (mutex_lock_interruptible(&zbdev->mutex))
4272+ return -EINTR;
4273+
4274+ ret = send_cmd(zbdev, CMD_CCA);
4275+ if (ret)
4276+ goto out;
4277+
4278+ if (wait_event_interruptible_timeout(zbdev->wq,
4279+ zbdev->status != STATUS_WAIT,
4280+ msecs_to_jiffies(1000)) > 0) {
4281+ if (zbdev->status != STATUS_SUCCESS) {
4282+ ret = -EBUSY;
4283+ goto out;
4284+ }
4285+ } else {
4286+ ret = -ETIMEDOUT;
4287+ goto out;
4288+ }
4289+
4290+ ret = send_cmd2(zbdev, CMD_SET_STATE, TX_MODE);
4291+ if (ret)
4292+ goto out;
4293+
4294+ if (wait_event_interruptible_timeout(zbdev->wq,
4295+ zbdev->status != STATUS_WAIT,
4296+ msecs_to_jiffies(1000)) > 0) {
4297+ if (zbdev->status != STATUS_SUCCESS) {
4298+ ret = -EBUSY;
4299+ goto out;
4300+ }
4301+ } else {
4302+ ret = -ETIMEDOUT;
4303+ goto out;
4304+ }
4305+
4306+ ret = send_block(zbdev, skb->len, skb->data);
4307+ if (ret)
4308+ goto out;
4309+
4310+ if (wait_event_interruptible_timeout(zbdev->wq,
4311+ zbdev->status != STATUS_WAIT,
4312+ msecs_to_jiffies(1000)) > 0) {
4313+ if (zbdev->status != STATUS_SUCCESS) {
4314+ ret = -EBUSY;
4315+ goto out;
4316+ }
4317+ } else {
4318+ ret = -ETIMEDOUT;
4319+ goto out;
4320+ }
4321+
4322+ ret = send_cmd2(zbdev, CMD_SET_STATE, RX_MODE);
4323+ if (ret)
4324+ goto out;
4325+
4326+ if (wait_event_interruptible_timeout(zbdev->wq,
4327+ zbdev->status != STATUS_WAIT,
4328+ msecs_to_jiffies(1000)) > 0) {
4329+ if (zbdev->status != STATUS_SUCCESS) {
4330+ ret = -EBUSY;
4331+ goto out;
4332+ }
4333+ } else {
4334+ ret = -ETIMEDOUT;
4335+ goto out;
4336+ }
4337+
4338+out:
4339+
4340+ mutex_unlock(&zbdev->mutex);
4341+ pr_debug("%s end\n", __func__);
4342+ return ret;
4343+}
4344+
4345+/*****************************************************************************
4346+ * Line discipline interface for IEEE 802.15.4 serial device
4347+ *****************************************************************************/
4348+
4349+static struct ieee802154_ops serial_ops = {
4350+ .owner = THIS_MODULE,
4351+ .xmit = ieee802154_serial_xmit,
4352+ .ed = ieee802154_serial_ed,
4353+ .set_channel = ieee802154_serial_set_channel,
4354+ .start = ieee802154_serial_start,
4355+ .stop = ieee802154_serial_stop,
4356+ .ieee_addr = ieee802154_serial_address,
4357+};
4358+
4359+/*
4360+ * Called when a tty is put into ZB line discipline. Called in process context.
4361+ * Returns 0 on success.
4362+ */
4363+static int
4364+ieee802154_tty_open(struct tty_struct *tty)
4365+{
4366+ struct zb_device *zbdev = tty->disc_data;
4367+ struct ieee802154_dev *dev;
4368+ int err;
4369+
4370+ pr_debug("Openning ldisc\n");
4371+ if (!capable(CAP_NET_ADMIN))
4372+ return -EPERM;
4373+
4374+ if (tty->disc_data)
4375+ return -EBUSY;
4376+
4377+ dev = ieee802154_alloc_device(sizeof(*zbdev), &serial_ops);
4378+ if (!dev)
4379+ return -ENOMEM;
4380+
4381+ zbdev = dev->priv;
4382+ zbdev->dev = dev;
4383+
4384+ mutex_init(&zbdev->mutex);
4385+ init_completion(&zbdev->open_done);
4386+ init_waitqueue_head(&zbdev->wq);
4387+
4388+ dev->extra_tx_headroom = 0;
4389+ /* only 2.4 GHz band */
4390+ dev->phy->channels_supported[0] = 0x7fff800;
4391+
4392+ dev->flags = IEEE802154_HW_OMIT_CKSUM;
4393+
4394+ dev->parent = tty->dev;
4395+
4396+ zbdev->tty = tty_kref_get(tty);
4397+
4398+ cleanup(zbdev);
4399+
4400+ tty->disc_data = zbdev;
4401+ tty->receive_room = MAX_DATA_SIZE;
4402+
4403+ /* FIXME: why is this needed. Note don't use ldisc_ref here as the
4404+ open path is before the ldisc is referencable */
4405+
4406+ if (tty->ldisc->ops->flush_buffer)
4407+ tty->ldisc->ops->flush_buffer(tty);
4408+ tty_driver_flush_buffer(tty);
4409+
4410+ err = ieee802154_register_device(dev);
4411+ if (err) {
4412+ printk(KERN_ERR "%s: device register failed\n", __func__);
4413+ goto out_free;
4414+ }
4415+
4416+ return 0;
4417+
4418+ ieee802154_unregister_device(zbdev->dev);
4419+
4420+out_free:
4421+ tty->disc_data = NULL;
4422+ tty_kref_put(tty);
4423+ zbdev->tty = NULL;
4424+
4425+ ieee802154_free_device(zbdev->dev);
4426+
4427+ return err;
4428+}
4429+
4430+/*
4431+ * Called when the tty is put into another line discipline or it hangs up. We
4432+ * have to wait for any cpu currently executing in any of the other zb_tty_*
4433+ * routines to finish before we can call zb_tty_close and free the
4434+ * zb_serial_dev struct. This routine must be called from process context, not
4435+ * interrupt or softirq context.
4436+ */
4437+static void
4438+ieee802154_tty_close(struct tty_struct *tty)
4439+{
4440+ struct zb_device *zbdev;
4441+
4442+ zbdev = tty->disc_data;
4443+ if (NULL == zbdev) {
4444+ printk(KERN_WARNING "%s: match is not found\n", __func__);
4445+ return;
4446+ }
4447+
4448+ tty->disc_data = NULL;
4449+ tty_kref_put(tty);
4450+ zbdev->tty = NULL;
4451+
4452+ ieee802154_unregister_device(zbdev->dev);
4453+
4454+ tty_ldisc_flush(tty);
4455+ tty_driver_flush_buffer(tty);
4456+
4457+ ieee802154_free_device(zbdev->dev);
4458+}
4459+
4460+/*
4461+ * Called on tty hangup in process context.
4462+ */
4463+static int
4464+ieee802154_tty_hangup(struct tty_struct *tty)
4465+{
4466+ ieee802154_tty_close(tty);
4467+ return 0;
4468+}
4469+
4470+/*
4471+ * Called in process context only. May be re-entered
4472+ * by multiple ioctl calling threads.
4473+ */
4474+static int
4475+ieee802154_tty_ioctl(struct tty_struct *tty, struct file *file,
4476+ unsigned int cmd, unsigned long arg)
4477+{
4478+ struct zb_device *zbdev;
4479+
4480+ pr_debug("cmd = 0x%x\n", cmd);
4481+
4482+ zbdev = tty->disc_data;
4483+ if (NULL == zbdev) {
4484+ pr_debug("match is not found\n");
4485+ return -EINVAL;
4486+ }
4487+
4488+ switch (cmd) {
4489+ case TCFLSH:
4490+ return tty_perform_flush(tty, arg);
4491+ default:
4492+ /* Try the mode commands */
4493+ return tty_mode_ioctl(tty, file, cmd, arg);
4494+ }
4495+}
4496+
4497+
4498+/*
4499+ * This can now be called from hard interrupt level as well
4500+ * as soft interrupt level or mainline.
4501+ */
4502+static void
4503+ieee802154_tty_receive(struct tty_struct *tty, const unsigned char *buf,
4504+ char *cflags, int count)
4505+{
4506+ struct zb_device *zbdev;
4507+ int i;
4508+
4509+ /* Debug info */
4510+ printk(KERN_INFO "%s, received %d bytes\n", __func__,
4511+ count);
4512+#ifdef DEBUG
4513+ print_hex_dump_bytes("ieee802154_tty_receive ", DUMP_PREFIX_NONE,
4514+ buf, count);
4515+#endif
4516+
4517+ /* Actual processing */
4518+ zbdev = tty->disc_data;
4519+ if (NULL == zbdev) {
4520+ printk(KERN_ERR "%s(): record for tty is not found\n",
4521+ __func__);
4522+ return;
4523+ }
4524+ for (i = 0; i < count; ++i)
4525+ process_char(zbdev, buf[i]);
4526+#if 0
4527+ if (tty->driver->flush_chars)
4528+ tty->driver->flush_chars(tty);
4529+#endif
4530+ tty_unthrottle(tty);
4531+}
4532+
4533+/*
4534+ * Line discipline device structure
4535+ */
4536+static struct tty_ldisc_ops ieee802154_ldisc = {
4537+ .owner = THIS_MODULE,
4538+ .magic = TTY_LDISC_MAGIC,
4539+ .name = "ieee802154-ldisc",
4540+ .open = ieee802154_tty_open,
4541+ .close = ieee802154_tty_close,
4542+ .hangup = ieee802154_tty_hangup,
4543+ .receive_buf = ieee802154_tty_receive,
4544+ .ioctl = ieee802154_tty_ioctl,
4545+};
4546+
4547+/*****************************************************************************
4548+ * Module service routinues
4549+ *****************************************************************************/
4550+
4551+static int __init ieee802154_serial_init(void)
4552+{
4553+ printk(KERN_INFO "Initializing ZigBee TTY interface\n");
4554+
4555+ if (tty_register_ldisc(N_IEEE802154, &ieee802154_ldisc) != 0) {
4556+ printk(KERN_ERR "%s: line discipline register failed\n",
4557+ __func__);
4558+ return -EINVAL;
4559+ }
4560+
4561+ return 0;
4562+}
4563+
4564+static void __exit ieee802154_serial_cleanup(void)
4565+{
4566+ if (tty_unregister_ldisc(N_IEEE802154) != 0)
4567+ printk(KERN_CRIT
4568+ "failed to unregister ZigBee line discipline.\n");
4569+}
4570+
4571+module_init(ieee802154_serial_init);
4572+module_exit(ieee802154_serial_cleanup);
4573+
4574+MODULE_LICENSE("GPL");
4575+MODULE_ALIAS_LDISC(N_IEEE802154);
4576+
4577diff --git a/drivers/ieee802154/spi_atben.c b/drivers/ieee802154/spi_atben.c
4578new file mode 100644
4579index 0000000..431bfe0
4580--- /dev/null
4581@@ -0,0 +1,421 @@
4582+/*
4583+ * spi_atben.c - SPI host look-alike for ATBEN
4584+ *
4585+ * Written 2011 by Werner Almesberger
4586+ *
4587+ * This program is free software; you can redistribute it and/or modify
4588+ * it under the terms of the GNU General Public License version 2
4589+ * as published by the Free Software Foundation.
4590+ */
4591+
4592+#include <linux/kernel.h>
4593+#include <linux/module.h>
4594+#include <linux/platform_device.h>
4595+#include <linux/gpio.h>
4596+#include <linux/delay.h>
4597+#include <linux/spi/spi.h>
4598+#include <linux/spi/at86rf230.h>
4599+#include <asm/mach-jz4740/base.h>
4600+
4601+#include "at86rf230.h"
4602+
4603+
4604+enum {
4605+ VDD_OFF = 1 << 2, /* VDD disable, PD02 */
4606+ MOSI = 1 << 8, /* CMD, PD08 */
4607+ SLP_TR = 1 << 9, /* CLK, PD09 */
4608+ MISO = 1 << 10, /* DAT0, PD10 */
4609+ SCLK = 1 << 11, /* DAT1, PD11 */
4610+ IRQ = 1 << 12, /* DAT2, PD12 */
4611+ nSEL = 1 << 13, /* DAT3/CD, PD13 */
4612+};
4613+
4614+#define PDPIN (prv->regs)
4615+#define PDDATS (prv->regs+0x14)
4616+#define PDDATC (prv->regs+0x18)
4617+
4618+
4619+struct atben_prv {
4620+ struct device *dev;
4621+ void __iomem *regs;
4622+ struct resource *ioarea;
4623+ struct at86rf230_platform_data
4624+ platform_data;
4625+ /* copy platform_data so that we can adapt .reset_data */
4626+};
4627+
4628+
4629+/* ----- ATBEN reset ------------------------------------------------------- */
4630+
4631+
4632+static void atben_reset(void *reset_data)
4633+{
4634+ struct atben_prv *prv = reset_data;
4635+ const int charge = nSEL | MOSI | SLP_TR | SCLK;
4636+ const int discharge = charge | IRQ | MISO;
4637+
4638+ dev_info(prv->dev, "atben_reset\n");
4639+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 1 << 2, 1 << 2);
4640+ jz_gpio_port_direction_output(JZ_GPIO_PORTD(0), discharge);
4641+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, discharge);
4642+ msleep(100); /* let power drop */
4643+
4644+ /*
4645+ * Hack: PD12/DAT2/IRQ is an active-high interrupt input, which is
4646+ * indicated by setting its direction bit to 1. We thus must not
4647+ * configure it as an "input".
4648+ */
4649+ jz_gpio_port_direction_input(JZ_GPIO_PORTD(0), MISO);
4650+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), charge, charge);
4651+ msleep(10); /* precharge caps */
4652+
4653+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, VDD_OFF | SLP_TR | SCLK);
4654+ msleep(10);
4655+}
4656+
4657+
4658+/* ----- SPI transfers ----------------------------------------------------- */
4659+
4660+
4661+static void rx_only(const struct atben_prv *prv, uint8_t *buf, int len)
4662+{
4663+ uint8_t v;
4664+
4665+ while (len--) {
4666+ writel(SCLK, PDDATS);
4667+ v = readl(PDPIN) & MISO ? 0x80 : 0;
4668+ writel(SCLK, PDDATC);
4669+
4670+ #define DO_BIT(m) \
4671+ writel(SCLK, PDDATS); \
4672+ if (readl(PDPIN) & MISO) \
4673+ v |= (m); \
4674+ writel(SCLK, PDDATC)
4675+
4676+ DO_BIT(0x40);
4677+ DO_BIT(0x20);
4678+ DO_BIT(0x10);
4679+ DO_BIT(0x08);
4680+ DO_BIT(0x04);
4681+ DO_BIT(0x02);
4682+ DO_BIT(0x01);
4683+
4684+ #undef DO_BIT
4685+
4686+ *buf++ = v;
4687+ }
4688+}
4689+
4690+
4691+static void tx_only(const struct atben_prv *prv, const uint8_t *buf, int len)
4692+{
4693+ uint8_t tv;
4694+
4695+ while (len--) {
4696+ tv = *buf++;
4697+
4698+ if (tv & 0x80) {
4699+ writel(MOSI, PDDATS);
4700+ goto b6_1;
4701+ } else {
4702+ writel(MOSI, PDDATC);
4703+ goto b6_0;
4704+ }
4705+
4706+ #define DO_BIT(m, this, next) \
4707+ this##_1: \
4708+ writel(SCLK, PDDATS); \
4709+ if (tv & (m)) { \
4710+ writel(SCLK, PDDATC); \
4711+ goto next##_1; \
4712+ } else { \
4713+ writel(MOSI | SCLK, PDDATC); \
4714+ goto next##_0; \
4715+ } \
4716+ this##_0: \
4717+ writel(SCLK, PDDATS); \
4718+ writel(SCLK, PDDATC); \
4719+ if (tv & (m)) { \
4720+ writel(MOSI, PDDATS); \
4721+ goto next##_1; \
4722+ } else { \
4723+ goto next##_0; \
4724+ }
4725+
4726+ DO_BIT(0x40, b6, b5);
4727+ DO_BIT(0x20, b5, b4);
4728+ DO_BIT(0x10, b4, b3);
4729+ DO_BIT(0x08, b3, b2);
4730+ DO_BIT(0x04, b2, b1);
4731+ DO_BIT(0x02, b1, b0);
4732+ DO_BIT(0x01, b0, done);
4733+
4734+ #undef DO_BIT
4735+
4736+done_1:
4737+done_0:
4738+ writel(SCLK, PDDATS);
4739+ writel(SCLK, PDDATC);
4740+ writel(SCLK, PDDATC); /* delay to meet t5 timing */
4741+ }
4742+}
4743+
4744+
4745+static void bidir(const struct atben_prv *prv, const uint8_t *tx, uint8_t *rx,
4746+ int len)
4747+{
4748+ uint8_t mask, tv, rv;
4749+
4750+ while (len--) {
4751+ tv = *tx++;
4752+ for (mask = 0x80; mask; mask >>= 1) {
4753+ if (tv & mask)
4754+ writel(MOSI, PDDATS);
4755+ else
4756+ writel(MOSI, PDDATC);
4757+ writel(SCLK, PDDATS);
4758+ if (readl(PDPIN) & MISO)
4759+ rv |= mask;
4760+ writel(SCLK, PDDATC);
4761+ }
4762+ *rx++ = rv;
4763+ }
4764+}
4765+
4766+
4767+static int atben_transfer(struct spi_device *spi, struct spi_message *msg)
4768+{
4769+ struct atben_prv *prv = spi_master_get_devdata(spi->master);
4770+ struct spi_transfer *xfer;
4771+ const uint8_t *tx;
4772+ uint8_t *rx;
4773+
4774+ if (unlikely(list_empty(&msg->transfers))) {
4775+ dev_err(prv->dev, "transfer is empty\n");
4776+ return -EINVAL;
4777+ }
4778+
4779+ msg->actual_length = 0;
4780+
4781+ writel(nSEL, PDDATC);
4782+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
4783+ tx = xfer->tx_buf;
4784+ rx = xfer->rx_buf;
4785+ msg->actual_length += xfer->len;
4786+
4787+ if (!tx)
4788+ rx_only(prv, rx, xfer->len);
4789+ else if (!rx)
4790+ tx_only(prv, tx, xfer->len);
4791+ else
4792+ bidir(prv, tx, rx, xfer->len);
4793+ }
4794+ writel(nSEL, PDDATS);
4795+
4796+ msg->status = 0;
4797+ msg->complete(msg->context);
4798+
4799+ return 0;
4800+}
4801+
4802+static int atben_setup(struct spi_device *spi)
4803+{
4804+ return 0;
4805+}
4806+
4807+
4808+/* ----- SPI master creation/removal --------------------------------------- */
4809+
4810+
4811+const static struct at86rf230_platform_data at86rf230_platform_data = {
4812+ .rstn = -1,
4813+ .slp_tr = JZ_GPIO_PORTD(9),
4814+ .dig2 = -1,
4815+ .reset = atben_reset,
4816+ /* set .reset_data later */
4817+};
4818+
4819+static int __devinit atben_probe(struct platform_device *pdev)
4820+{
4821+ struct spi_board_info board_info = {
4822+ .modalias = "at86rf230",
4823+ /* set .irq later */
4824+ .chip_select = 0,
4825+ .bus_num = -1,
4826+ .max_speed_hz = 8 * 1000 * 1000,
4827+ };
4828+
4829+ struct spi_master *master;
4830+ struct atben_prv *prv;
4831+ struct resource *regs;
4832+ struct spi_device *spi;
4833+ int err = -ENXIO;
4834+
4835+ master = spi_alloc_master(&pdev->dev, sizeof(*prv));
4836+ if (!master)
4837+ return -ENOMEM;
4838+
4839+ prv = spi_master_get_devdata(master);
4840+ prv->dev = &pdev->dev;
4841+ platform_set_drvdata(pdev, spi_master_get(master));
4842+
4843+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
4844+ master->bus_num = pdev->id;
4845+ master->num_chipselect = 1;
4846+ master->setup = atben_setup;
4847+ master->transfer = atben_transfer;
4848+
4849+ dev_dbg(prv->dev, "Setting up ATBEN SPI\n");
4850+
4851+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4852+ if (!regs) {
4853+ dev_err(prv->dev, "no IORESOURCE_MEM\n");
4854+ err = -ENOENT;
4855+ goto out_master;
4856+ }
4857+ prv->ioarea = request_mem_region(regs->start, resource_size(regs),
4858+ pdev->name);
4859+ if (!prv->ioarea) {
4860+ dev_err(prv->dev, "can't request ioarea\n");
4861+ goto out_master;
4862+ }
4863+
4864+ prv->regs = ioremap(regs->start, resource_size(regs));
4865+ if (!prv->regs) {
4866+ dev_err(prv->dev, "can't ioremap\n");
4867+ goto out_ioarea;
4868+ }
4869+
4870+ board_info.irq = platform_get_irq(pdev, 0);
4871+ if (board_info.irq < 0) {
4872+ dev_err(prv->dev, "can't get GPIO irq\n");
4873+ err = -ENOENT;
4874+ goto out_regs;
4875+ }
4876+
4877+ err = spi_register_master(master);
4878+ if (err) {
4879+ dev_err(prv->dev, "can't register master\n");
4880+ goto out_regs;
4881+ }
4882+
4883+ prv->platform_data = at86rf230_platform_data;
4884+ prv->platform_data.reset_data = prv;
4885+ board_info.platform_data = &prv->platform_data;
4886+
4887+ spi = spi_new_device(master, &board_info);
4888+ if (!spi) {
4889+ dev_err(&pdev->dev, "can't create new device for %s\n",
4890+ board_info.modalias);
4891+ err = -ENXIO;
4892+ goto out_registered;
4893+ }
4894+
4895+ dev_info(&spi->dev, "ATBEN ready for mischief (IRQ %d)\n",
4896+ board_info.irq);
4897+
4898+ return 0;
4899+
4900+out_registered:
4901+ spi_unregister_master(master);
4902+
4903+out_regs:
4904+ iounmap(prv->regs);
4905+
4906+out_ioarea:
4907+ release_resource(prv->ioarea);
4908+ kfree(prv->ioarea);
4909+
4910+out_master:
4911+ platform_set_drvdata(pdev, NULL);
4912+ spi_master_put(master);
4913+
4914+ return err;
4915+}
4916+
4917+static int __devexit atben_remove(struct platform_device *pdev)
4918+{
4919+ struct spi_master *master = platform_get_drvdata(pdev);
4920+ struct atben_prv *prv = spi_master_get_devdata(master);
4921+
4922+// restore GPIOs
4923+
4924+ spi_unregister_master(master);
4925+
4926+ iounmap(prv->regs);
4927+
4928+ release_resource(prv->ioarea);
4929+ kfree(prv->ioarea);
4930+
4931+ platform_set_drvdata(pdev, NULL);
4932+ spi_master_put(master);
4933+
4934+ return 0;
4935+}
4936+
4937+static struct platform_driver atben_driver = {
4938+ .driver = {
4939+ .name = "spi_atben",
4940+ .owner = THIS_MODULE,
4941+ },
4942+ .remove = __devexit_p(atben_remove),
4943+};
4944+
4945+static struct resource atben_resources[] = {
4946+ {
4947+ .start = JZ4740_GPIO_BASE_ADDR+0x300,
4948+ .end = JZ4740_GPIO_BASE_ADDR+0x3ff,
4949+ .flags = IORESOURCE_MEM,
4950+ },
4951+ {
4952+ /* set start and end later */
4953+ .flags = IORESOURCE_IRQ,
4954+ },
4955+};
4956+
4957+static struct platform_device atben_device = {
4958+ .name = "spi_atben",
4959+ .id = -1,
4960+ .num_resources = ARRAY_SIZE(atben_resources),
4961+ .resource = atben_resources,
4962+};
4963+
4964+/*
4965+ * Registering the platform device just to probe it immediately afterwards
4966+ * seems a little circuitous. Need to see if there's a better way.
4967+ *
4968+ * What we actually should do is this:
4969+ * - in module init, register the device
4970+ * - maybe probe as well, but keep the device also if the probe fails
4971+ * (due to a conflicting driver already occupying the 8:10 slot)
4972+ * - have a means for user space to kick off driver probing, e.g., when
4973+ * anything about the 8:10 slot changes
4974+ */
4975+
4976+static int __init atben_init(void)
4977+{
4978+ int err;
4979+
4980+ err = platform_device_register(&atben_device);
4981+ if (err)
4982+ return err;
4983+
4984+ atben_resources[1].start = atben_resources[1].end =
4985+ gpio_to_irq(JZ_GPIO_PORTD(12));
4986+
4987+ return platform_driver_probe(&atben_driver, atben_probe);
4988+}
4989+
4990+static void __exit atben_exit(void)
4991+{
4992+ platform_driver_unregister(&atben_driver);
4993+ platform_device_unregister(&atben_device);
4994+}
4995+
4996+module_init(atben_init);
4997+module_exit(atben_exit);
4998+
4999+
5000+MODULE_DESCRIPTION("ATBEN SPI Controller Driver");
5001+MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
5002+MODULE_LICENSE("GPL");
5003diff --git a/drivers/ieee802154/spi_atusb.c b/drivers/ieee802154/spi_atusb.c
5004new file mode 100644
5005index 0000000..04d9fb3
5006--- /dev/null
5007@@ -0,0 +1,750 @@
5008+/*
5009+ * spi_atusb - SPI host look-alike for ATUSB
5010+ *
5011+ * Copyright (c) 2011 Richard Sharpe <realrichardsharpe@gmail.com>
5012+ * Copyright (c) 2011 Stefan Schmidt <stefan@datenfreihafen.org>
5013+ * Copyright (c) 2011 Werner Almesberger <werner@almesberger.net>
5014+ *
5015+ * This program is free software; you can redistribute it and/or
5016+ * modify it under the terms of the GNU General Public License as
5017+ * published by the Free Software Foundation, version 2
5018+ *
5019+ */
5020+
5021+/*
5022+ * - implement more robust interrupt synchronization
5023+ * - check URB killing in atusb_disconnect for races
5024+ * - switch from bulk to interrupt endpoint
5025+ * - implement buffer read without extra copy
5026+ * - harmonize indentation style
5027+ * - mv atusb.c ../ieee802.15.4/spi_atusb.c, or maybe atrf_atusb.c or such
5028+ * - check module load/unload
5029+ * - review dev_* severity levels
5030+ */
5031+
5032+#include <linux/kernel.h>
5033+#include <linux/module.h>
5034+#include <linux/platform_device.h>
5035+#include <linux/jiffies.h>
5036+#include <linux/timer.h>
5037+#include <linux/interrupt.h>
5038+#include <linux/usb.h>
5039+#include <linux/spi/spi.h>
5040+#include <linux/spi/at86rf230.h>
5041+
5042+#include "at86rf230.h"
5043+
5044+
5045+#define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after
5046+ waiting this long */
5047+
5048+#define VENDOR_ID 0x20b7
5049+#define PRODUCT_ID 0x1540
5050+
5051+/* The devices we work with */
5052+static const struct usb_device_id atusb_device_table[] = {
5053+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
5054+ { },
5055+};
5056+MODULE_DEVICE_TABLE(usb, atusb_device_table);
5057+
5058+#define ATUSB_BUILD_SIZE 256
5059+struct atusb_local {
5060+ struct usb_device * udev;
5061+ /* The interface to the RF part info, if applicable */
5062+ uint8_t ep0_atusb_major;
5063+ uint8_t ep0_atusb_minor;
5064+ uint8_t atusb_hw_type;
5065+ struct spi_master *master;
5066+ int slave_irq;
5067+ struct urb *irq_urb;
5068+ uint8_t irq_buf; /* receive irq serial here*/
5069+ uint8_t irq_seen; /* last irq serial from bulk */
5070+ uint8_t irq_sync; /* last irq serial from WRITE2_SYNC */
5071+ struct tasklet_struct task; /* interrupt delivery tasklet */
5072+ struct timer_list timer; /* delay, for interrupt synch */
5073+ struct at86rf230_platform_data platform_data;
5074+ /* copy platform_data so that we can adapt .reset_data */
5075+ struct spi_device *spi;
5076+// unsigned char buffer[3];
5077+ unsigned char buffer[260]; /* XXL, just in case */
5078+ struct spi_message *msg;
5079+};
5080+
5081+/* Commands to our device. Make sure this is synced with the firmware */
5082+enum atspi_requests {
5083+ ATUSB_ID = 0x00, /* system status/control grp */
5084+ ATUSB_BUILD,
5085+ ATUSB_RESET,
5086+ ATUSB_RF_RESET = 0x10, /* debug/test group */
5087+ ATUSB_POLL_INT,
5088+ ATUSB_TEST, /* atusb-sil only */
5089+ ATUSB_TIMER,
5090+ ATUSB_GPIO,
5091+ ATUSB_SLP_TR,
5092+ ATUSB_GPIO_CLEANUP,
5093+ ATUSB_REG_WRITE = 0x20, /* transceiver group */
5094+ ATUSB_REG_READ,
5095+ ATUSB_BUF_WRITE,
5096+ ATUSB_BUF_READ,
5097+ ATUSB_SRAM_WRITE,
5098+ ATUSB_SRAM_READ,
5099+ ATUSB_SPI_WRITE = 0x30, /* SPI group */
5100+ ATUSB_SPI_READ1,
5101+ ATUSB_SPI_READ2,
5102+ ATUSB_SPI_WRITE2_SYNC,
5103+};
5104+
5105+/*
5106+ * Direction bRequest wValue wIndex wLength
5107+ *
5108+ * ->host ATUSB_ID - - 3
5109+ * ->host ATUSB_BUILD - - #bytes
5110+ * host-> ATUSB_RESET - - 0
5111+ *
5112+ * host-> ATUSB_RF_RESET - - 0
5113+ * ->host ATUSB_POLL_INT - - 1
5114+ * host-> ATUSB_TEST - - 0
5115+ * ->host ATUSB_TIMER - - #bytes (6)
5116+ * ->host ATUSB_GPIO dir+data mask+p# 3
5117+ * host-> ATUSB_SLP_TR - - 0
5118+ * host-> ATUSB_GPIO_CLEANUP - - 0
5119+ *
5120+ * host-> ATUSB_REG_WRITE value addr 0
5121+ * ->host ATUSB_REG_READ - addr 1
5122+ * host-> ATUSB_BUF_WRITE - - #bytes
5123+ * ->host ATUSB_BUF_READ - - #bytes
5124+ * host-> ATUSB_SRAM_WRITE - addr #bytes
5125+ * ->host ATUSB_SRAM_READ - addr #bytes
5126+ *
5127+ * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
5128+ * ->host ATUSB_SPI_READ1 byte0 - #bytes
5129+ * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
5130+ * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
5131+ */
5132+
5133+#define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
5134+#define ATUSB_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT)
5135+
5136+
5137+/* ----- Control transfers ------------------------------------------------- */
5138+
5139+
5140+static int atusb_async_errchk(struct urb *urb)
5141+{
5142+ struct atusb_local *atusb = urb->context;
5143+ struct spi_message *msg = atusb->msg;
5144+ struct usb_device *dev = atusb->udev;
5145+
5146+ if (!urb->status) {
5147+ dev_dbg(&dev->dev, "atusb_async_errchk OK len %d\n",
5148+ urb->actual_length);
5149+ return 0;
5150+ }
5151+
5152+ if (urb->status != -ENOENT && urb->status != -ECONNRESET &&
5153+ urb->status != -ESHUTDOWN)
5154+ dev_info(&dev->dev, "atusb_async_errchk FAIL error %d\n",
5155+ urb->status);
5156+
5157+ msg->actual_length = 0;
5158+
5159+ return urb->status;
5160+}
5161+
5162+static void atusb_async_finish(struct urb *urb)
5163+{
5164+ struct atusb_local *atusb = urb->context;
5165+ struct spi_message *msg = atusb->msg;
5166+
5167+ msg->status = urb->status;
5168+ msg->complete(msg->context);
5169+
5170+ kfree(urb->setup_packet);
5171+ usb_free_urb(urb);
5172+}
5173+
5174+static void atusb_ctrl_cb(struct urb *urb)
5175+{
5176+ atusb_async_errchk(urb);
5177+ atusb_async_finish(urb);
5178+}
5179+
5180+static void atusb_timer(unsigned long data)
5181+{
5182+ struct urb *urb = (void *) data;
5183+
5184+ dev_warn(&urb->dev->dev, "atusb_timer\n");
5185+ atusb_async_finish(urb);
5186+}
5187+
5188+static void atusb_ctrl_cb_sync(struct urb *urb)
5189+{
5190+ struct atusb_local *atusb = urb->context;
5191+
5192+ /* @@@ needs locking/atomic */
5193+ if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) {
5194+ atusb_async_finish(urb);
5195+ return;
5196+ }
5197+
5198+ BUG_ON(timer_pending(&atusb->timer));
5199+ atusb->timer.expires = jiffies+msecs_to_jiffies(SYNC_TIMEOUT_MS);
5200+ atusb->timer.data = (unsigned long) urb;
5201+ add_timer(&atusb->timer);
5202+}
5203+
5204+static void atusb_read_fb_cb(struct urb *urb)
5205+{
5206+ struct atusb_local *atusb = urb->context;
5207+ struct spi_message *msg = atusb->msg;
5208+ const struct spi_transfer *xfer;
5209+ uint8_t *rx;
5210+
5211+ if (!atusb_async_errchk(urb)) {
5212+ BUG_ON(!urb->actual_length);
5213+
5214+ xfer = list_first_entry(&msg->transfers, struct spi_transfer,
5215+ transfer_list);
5216+ rx = xfer->rx_buf;
5217+ rx[1] = atusb->buffer[0];
5218+
5219+ xfer = list_entry(xfer->transfer_list.next,
5220+ struct spi_transfer, transfer_list);
5221+ memcpy(xfer->rx_buf, atusb->buffer+1, urb->actual_length-1);
5222+ }
5223+
5224+ atusb_async_finish(urb);
5225+}
5226+
5227+static int submit_control_msg(struct atusb_local *atusb,
5228+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
5229+ void *data, __u16 size, usb_complete_t complete_fn, void *context)
5230+{
5231+ struct usb_device *dev = atusb->udev;
5232+ struct usb_ctrlrequest *req;
5233+ struct urb *urb;
5234+ int retval = -ENOMEM;
5235+
5236+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
5237+ if (!req)
5238+ return -ENOMEM;
5239+
5240+ req->bRequest = request;
5241+ req->bRequestType = requesttype;
5242+ req->wValue = cpu_to_le16(value);
5243+ req->wIndex = cpu_to_le16(index);
5244+ req->wLength = cpu_to_le16(size);
5245+
5246+ urb = usb_alloc_urb(0, GFP_KERNEL);
5247+ if (!urb)
5248+ goto out_nourb;
5249+
5250+ usb_fill_control_urb(urb, dev,
5251+ requesttype == ATUSB_FROM_DEV ?
5252+ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0),
5253+ (unsigned char *) req, data, size, complete_fn, context);
5254+
5255+ retval = usb_submit_urb(urb, GFP_KERNEL);
5256+ if (!retval)
5257+ return 0;
5258+ dev_warn(&dev->dev, "failed submitting read urb, error %d",
5259+ retval);
5260+ retval = retval == -ENOMEM ? retval : -EIO;
5261+
5262+ usb_free_urb(urb);
5263+out_nourb:
5264+ kfree(req);
5265+
5266+ return retval;
5267+}
5268+
5269+
5270+/* ----- SPI transfers ----------------------------------------------------- */
5271+
5272+
5273+static int atusb_read1(struct atusb_local *atusb,
5274+ uint8_t tx, uint8_t *rx, int len)
5275+{
5276+ dev_dbg(&atusb->udev->dev, "atusb_read1: tx = 0x%x\n", tx);
5277+ return submit_control_msg(atusb,
5278+ ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
5279+ rx, 1, atusb_ctrl_cb, atusb);
5280+}
5281+
5282+static int atusb_read_fb(struct atusb_local *atusb,
5283+ uint8_t tx, uint8_t *rx0, uint8_t *rx, int len)
5284+{
5285+ dev_dbg(&atusb->udev->dev, "atusb_read_fb: tx = 0x%x\n", tx);
5286+ return submit_control_msg(atusb,
5287+ ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
5288+ atusb->buffer, len+1, atusb_read_fb_cb, atusb);
5289+}
5290+
5291+static int atusb_write(struct atusb_local *atusb,
5292+ uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len)
5293+{
5294+ dev_dbg(&atusb->udev->dev,
5295+ "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1);
5296+
5297+ /*
5298+ * The AT86RF230 driver sometimes requires a transceiver state
5299+ * transition to be an interrupt barrier. This is the case after
5300+ * writing FORCE_TX_ON to the TRX_CMD field in the TRX_STATE register.
5301+ *
5302+ * Since there is no other means of notification, we just decode the
5303+ * transfer and do a bit of pattern matching.
5304+ */
5305+ if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) &&
5306+ (tx1 & 0x1f) == STATE_FORCE_TX_ON)
5307+ return submit_control_msg(atusb,
5308+ ATUSB_SPI_WRITE2_SYNC, ATUSB_FROM_DEV, tx0, tx1,
5309+ &atusb->irq_sync, 1, atusb_ctrl_cb_sync, atusb);
5310+ else
5311+ return submit_control_msg(atusb,
5312+ ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
5313+ (uint8_t *) tx, len, atusb_ctrl_cb, atusb);
5314+}
5315+
5316+static int atusb_transfer(struct spi_device *spi, struct spi_message *msg)
5317+{
5318+ struct atusb_local *atusb = spi_master_get_devdata(spi->master);
5319+ struct spi_transfer *xfer;
5320+ struct spi_transfer *x[2];
5321+ int n;
5322+ const uint8_t *tx;
5323+ uint8_t *rx;
5324+ int len;
5325+ int retval = 0;
5326+
5327+ if (unlikely(list_empty(&msg->transfers))) {
5328+ dev_err(&atusb->udev->dev, "transfer is empty\n");
5329+ return -EINVAL;
5330+ }
5331+
5332+ atusb->msg = msg;
5333+
5334+ /* Classify the request */
5335+ n = 0;
5336+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
5337+ if (n == ARRAY_SIZE(x)) {
5338+ dev_err(&atusb->udev->dev, "too many transfers\n");
5339+ return -EINVAL;
5340+ }
5341+ x[n] = xfer;
5342+ n++;
5343+ }
5344+
5345+ tx = x[0]->tx_buf;
5346+ rx = x[0]->rx_buf;
5347+ len = x[0]->len;
5348+
5349+ msg->actual_length = len;
5350+
5351+ if (!tx || len != 2)
5352+ goto bad_req;
5353+ if (n == 1) {
5354+ if (rx) {
5355+ dev_dbg(&atusb->udev->dev, "read 1\n");
5356+ retval = atusb_read1(atusb, tx[0], rx+1, len-1);
5357+ } else {
5358+ dev_dbg(&atusb->udev->dev, "write 2\n");
5359+ /*
5360+ * Don't take our clock away !! ;-)
5361+ */
5362+ if (tx[0] == (CMD_REG | CMD_WRITE | RG_TRX_CTRL_0)) {
5363+ msg->status = 0;
5364+ msg->complete(msg->context);
5365+ } else {
5366+ retval = atusb_write(atusb,
5367+ tx[0], tx[1], NULL, 0);
5368+ }
5369+ }
5370+ } else {
5371+ if (x[0]->rx_buf) {
5372+ if (x[1]->tx_buf || !x[1]->rx_buf)
5373+ goto bad_req;
5374+ dev_dbg(&atusb->udev->dev, "read 1+\n");
5375+ retval = atusb_read_fb(atusb, tx[0], rx+1,
5376+ x[1]->rx_buf, x[1]->len);
5377+ } else {
5378+ if (!x[1]->tx_buf ||x[1]->rx_buf)
5379+ goto bad_req;
5380+ dev_dbg(&atusb->udev->dev, "write 2+n\n");
5381+ retval = atusb_write(atusb, tx[0], tx[1],
5382+ x[1]->tx_buf, x[1]->len);
5383+ }
5384+ }
5385+ return retval;
5386+
5387+bad_req:
5388+ dev_err(&atusb->udev->dev, "unrecognized request:\n");
5389+ list_for_each_entry(xfer, &msg->transfers, transfer_list)
5390+ dev_err(&atusb->udev->dev, "%stx %srx len %u\n",
5391+ xfer->tx_buf ? "" : "!", xfer->rx_buf ? " " : "!",
5392+ xfer->len);
5393+ return -EINVAL;
5394+}
5395+
5396+static int atusb_setup(struct spi_device *spi)
5397+{
5398+ return 0;
5399+}
5400+
5401+
5402+/* ----- Interrupt handling ------------------------------------------------ */
5403+
5404+
5405+static void atusb_tasklet(unsigned long data)
5406+{
5407+ struct atusb_local *atusb = (void *) data;
5408+
5409+ generic_handle_irq(atusb->slave_irq);
5410+}
5411+
5412+static void atusb_irq(struct urb *urb)
5413+{
5414+ struct atusb_local *atusb = urb->context;
5415+
5416+ dev_dbg(&urb->dev->dev, "atusb_irq (%d), seen %d sync %d\n",
5417+ urb->status, atusb->irq_buf, atusb->irq_sync);
5418+ if (!urb->status) {
5419+ atusb->irq_seen = atusb->irq_buf;
5420+ if (atusb->irq_sync == atusb->irq_seen &&
5421+ try_to_del_timer_sync(&atusb->timer) == 1)
5422+ atusb_async_finish((struct urb *) atusb->timer.data);
5423+ }
5424+ usb_free_urb(urb);
5425+ atusb->irq_urb = NULL;
5426+ tasklet_schedule(&atusb->task);
5427+}
5428+
5429+static int atusb_arm_interrupt(struct atusb_local *atusb)
5430+{
5431+ struct usb_device *dev = atusb->udev;
5432+ struct urb *urb;
5433+ int retval = -ENOMEM;
5434+
5435+ BUG_ON(atusb->irq_urb);
5436+
5437+ dev_vdbg(&dev->dev, "atusb_arm_interrupt\n");
5438+ urb = usb_alloc_urb(0, GFP_KERNEL);
5439+ if (!urb) {
5440+ dev_err(&dev->dev,
5441+ "atusb_arm_interrupt: usb_alloc_urb failed\n");
5442+ return -ENOMEM;
5443+ }
5444+
5445+ usb_fill_bulk_urb(urb, dev, usb_rcvbulkpipe(dev, 1),
5446+ &atusb->irq_buf, 1, atusb_irq, atusb);
5447+ atusb->irq_urb = urb;
5448+ retval = usb_submit_urb(urb, GFP_KERNEL);
5449+ if (!retval)
5450+ return 0;
5451+
5452+ dev_err(&dev->dev, "failed submitting bulk urb, error %d\n", retval);
5453+ retval = retval == -ENOMEM ? retval : -EIO;
5454+
5455+ usb_free_urb(urb);
5456+
5457+ return retval;
5458+}
5459+
5460+static void atusb_irq_mask(struct irq_data *data)
5461+{
5462+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5463+
5464+ dev_vdbg(&atusb->udev->dev, "atusb_irq_mask\n");
5465+ tasklet_disable_nosync(&atusb->task);
5466+}
5467+
5468+static void atusb_irq_unmask(struct irq_data *data)
5469+{
5470+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5471+
5472+ dev_vdbg(&atusb->udev->dev, "atusb_irq_unmask\n");
5473+ tasklet_enable(&atusb->task);
5474+}
5475+
5476+static void atusb_irq_ack(struct irq_data *data)
5477+{
5478+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5479+
5480+ dev_vdbg(&atusb->udev->dev, "atusb_irq_ack\n");
5481+ atusb_arm_interrupt(atusb);
5482+}
5483+
5484+static struct irq_chip atusb_irq_chip = {
5485+ .name = "atusb-slave",
5486+ .irq_mask = atusb_irq_mask,
5487+ .irq_unmask = atusb_irq_unmask,
5488+ .irq_ack = atusb_irq_ack,
5489+};
5490+
5491+
5492+/* ----- Transceiver reset ------------------------------------------------- */
5493+
5494+
5495+static void atusb_reset(void *reset_data)
5496+{
5497+ int retval;
5498+ struct atusb_local *atusb = reset_data;
5499+
5500+ retval = usb_control_msg(atusb->udev,
5501+ usb_rcvctrlpipe(atusb->udev, 0),
5502+ ATUSB_RF_RESET, ATUSB_TO_DEV, 0, 0,
5503+ NULL, 0, 1000);
5504+ if (retval < 0) {
5505+ dev_err(&atusb->udev->dev,
5506+ "%s: error doing reset retval = %d\n",
5507+ __func__, retval);
5508+ }
5509+}
5510+
5511+
5512+/* ----- Firmware version information -------------------------------------- */
5513+
5514+
5515+static int atusb_get_and_show_revision(struct atusb_local *atusb)
5516+{
5517+ struct usb_device *dev = atusb->udev;
5518+ int retval;
5519+
5520+ /* Get a couple of the ATMega Firmware values */
5521+ retval = usb_control_msg(dev,
5522+ usb_rcvctrlpipe(dev, 0),
5523+ ATUSB_ID, ATUSB_FROM_DEV, 0, 0,
5524+ atusb->buffer, 3, 1000);
5525+ if (retval < 0) {
5526+ dev_info(&dev->dev,
5527+ "failed submitting urb for ATUSB_ID, error %d\n", retval);
5528+ return retval == -ENOMEM ? retval : -EIO;
5529+ }
5530+
5531+ atusb->ep0_atusb_major = atusb->buffer[0];
5532+ atusb->ep0_atusb_minor = atusb->buffer[1];
5533+ atusb->atusb_hw_type = atusb->buffer[2];
5534+ dev_info(&dev->dev,
5535+ "Firmware: major: %u, minor: %u, hardware type: %u\n",
5536+ atusb->ep0_atusb_major, atusb->ep0_atusb_minor,
5537+ atusb->atusb_hw_type);
5538+
5539+ return 0;
5540+}
5541+
5542+static int atusb_get_and_show_build(struct atusb_local *atusb)
5543+{
5544+ struct usb_device *dev = atusb->udev;
5545+ char build[ATUSB_BUILD_SIZE+1];
5546+ int retval;
5547+
5548+ retval = usb_control_msg(dev,
5549+ usb_rcvctrlpipe(atusb->udev, 0),
5550+ ATUSB_BUILD, ATUSB_FROM_DEV, 0, 0,
5551+ build, ATUSB_BUILD_SIZE, 1000);
5552+ if (retval < 0) {
5553+ dev_err(&dev->dev,
5554+ "failed submitting urb for ATUSB_BUILD, error %d\n",
5555+ retval);
5556+ return retval == -ENOMEM ? retval : -EIO;
5557+ }
5558+
5559+ build[retval] = 0;
5560+ dev_info(&dev->dev, "Firmware: build %s\n", build);
5561+
5562+ return 0;
5563+}
5564+
5565+
5566+/* ----- Setup ------------------------------------------------------------- */
5567+
5568+
5569+struct at86rf230_platform_data at86rf230_platform_data = {
5570+ .rstn = -1,
5571+ .slp_tr = -1,
5572+ .dig2 = -1,
5573+ .reset = atusb_reset,
5574+ /* set .reset_data later */
5575+};
5576+
5577+static int atusb_probe(struct usb_interface *interface,
5578+ const struct usb_device_id *id)
5579+{
5580+ struct spi_board_info board_info = {
5581+ .modalias = "at86rf230",
5582+ /* set .irq later */
5583+ .chip_select = 0,
5584+ .bus_num = -1,
5585+ .max_speed_hz = 8 * 1000 * 1000,
5586+ };
5587+
5588+ struct usb_device *udev = interface_to_usbdev(interface);
5589+ struct atusb_local *atusb = NULL;
5590+ struct spi_master *master;
5591+ int retval;
5592+
5593+ /*
5594+ * Ignore all interfaces used for DFU, i.e., everything while in the
5595+ * boot loader, and interface #1 when in the application.
5596+ */
5597+ if (interface->cur_altsetting->desc.bInterfaceClass !=
5598+ USB_CLASS_VENDOR_SPEC) {
5599+ dev_dbg(&udev->dev,
5600+ "Ignoring interface with class 0x%02x\n",
5601+ interface->cur_altsetting->desc.bInterfaceClass);
5602+ return -ENODEV;
5603+ }
5604+
5605+ master = spi_alloc_master(&udev->dev, sizeof(*atusb));
5606+ if (!master)
5607+ return -ENOMEM;
5608+
5609+ atusb = spi_master_get_devdata(master);
5610+
5611+ atusb->udev = usb_get_dev(udev);
5612+ usb_set_intfdata(interface, atusb);
5613+
5614+ atusb->master = spi_master_get(master);
5615+
5616+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
5617+ master->bus_num = -1;
5618+ master->num_chipselect = 1;
5619+ master->setup = atusb_setup;
5620+ master->transfer = atusb_transfer;
5621+
5622+ atusb->slave_irq = irq_alloc_desc(numa_node_id());
5623+ if (atusb->slave_irq < 0) {
5624+ dev_err(&udev->dev, "can't allocate slave irq\n");
5625+ retval = -ENXIO;
5626+ goto err_free;
5627+ }
5628+
5629+ set_irq_chip_data(atusb->slave_irq, atusb);
5630+ set_irq_chip_and_handler(atusb->slave_irq, &atusb_irq_chip,
5631+ handle_level_irq);
5632+
5633+ /* FIXME prepare USB IRQ */
5634+
5635+ retval = spi_register_master(master);
5636+ if (retval < 0) {
5637+ dev_err(&udev->dev, "can't register spi master\n");
5638+ goto err_slave_irq;
5639+ }
5640+
5641+ atusb->platform_data = at86rf230_platform_data;
5642+ atusb->platform_data.reset_data = atusb;
5643+ board_info.platform_data = &atusb->platform_data;
5644+ board_info.irq = atusb->slave_irq;
5645+
5646+ init_timer(&atusb->timer);
5647+ atusb->timer.function = atusb_timer;
5648+
5649+ tasklet_init(&atusb->task, atusb_tasklet, (unsigned long) atusb);
5650+ tasklet_disable(&atusb->task);
5651+ atusb_arm_interrupt(atusb);
5652+
5653+ if (atusb_get_and_show_revision(atusb) < 0)
5654+ goto err_master;
5655+ if (atusb_get_and_show_build(atusb) < 0)
5656+ goto err_master;
5657+
5658+ atusb->spi = spi_new_device(master, &board_info);
5659+ if (!atusb->spi) {
5660+ dev_err(&udev->dev, "can't create new device for %s\n",
5661+ board_info.modalias);
5662+ goto err_master;
5663+ }
5664+
5665+ dev_info(&atusb->spi->dev,
5666+ "ATUSB ready for mischief (IRQ %d)\n", board_info.irq);
5667+
5668+ return 0;
5669+
5670+err_master:
5671+ /*
5672+ * If we come here from a partially successful driver initialization,
5673+ * we don't really know how much it has done. In particular, it may
5674+ * have triggered an interrupt and thus removed the interrupt URB and
5675+ * maybe scheduled the tasklet.
5676+ */
5677+ tasklet_disable(&atusb->task);
5678+ if (atusb->irq_urb)
5679+ usb_kill_urb(atusb->irq_urb);
5680+ spi_master_put(atusb->master);
5681+err_slave_irq:
5682+ set_irq_chained_handler(atusb->slave_irq, NULL);
5683+ set_irq_chip_data(atusb->slave_irq, NULL);
5684+ irq_free_desc(atusb->slave_irq);
5685+err_free:
5686+ return retval;
5687+}
5688+
5689+static void atusb_disconnect(struct usb_interface *interface)
5690+{
5691+ struct atusb_local *atusb = usb_get_intfdata(interface);
5692+ struct spi_master *master = atusb->master;
5693+
5694+ tasklet_disable(&atusb->task);
5695+ /* @@@ this needs some extra protecion - wa */
5696+ if (atusb->irq_urb)
5697+ usb_kill_urb(atusb->irq_urb);
5698+
5699+ BUG_ON(timer_pending(&atusb->timer));
5700+
5701+ usb_set_intfdata(interface, NULL);
5702+ usb_put_dev(atusb->udev);
5703+
5704+ spi_dev_put(atusb->spi);
5705+
5706+ spi_unregister_master(master);
5707+
5708+ set_irq_chained_handler(atusb->slave_irq, NULL);
5709+ set_irq_chip_data(atusb->slave_irq, NULL);
5710+ irq_free_desc(atusb->slave_irq);
5711+
5712+ spi_master_put(master);
5713+}
5714+
5715+void atusb_release(struct device *dev)
5716+{
5717+ return;
5718+}
5719+
5720+static struct usb_driver atusb_driver = {
5721+ .name = "atusb_ben-wpan",
5722+ .probe = atusb_probe,
5723+ .disconnect = atusb_disconnect,
5724+ .id_table = atusb_device_table,
5725+};
5726+
5727+static struct platform_device atusb_device = {
5728+ .name = "spi_atusb",
5729+ .id = -1,
5730+ .dev.release = atusb_release,
5731+};
5732+
5733+static int __init atusb_init(void)
5734+{
5735+ int retval;
5736+
5737+ retval = platform_device_register(&atusb_device);
5738+ if (retval)
5739+ return retval;
5740+
5741+ return usb_register(&atusb_driver);
5742+}
5743+
5744+static void __exit atusb_exit(void)
5745+{
5746+ usb_deregister(&atusb_driver);
5747+ platform_device_unregister(&atusb_device);
5748+}
5749+
5750+module_init (atusb_init);
5751+module_exit (atusb_exit);
5752+
5753+MODULE_AUTHOR("Richard Sharpe <realrichardsharpe@gmail.com>");
5754+MODULE_AUTHOR("Stefan Schmidt <stefan@datenfreihafen.org>");
5755+MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
5756+MODULE_DESCRIPTION("ATUSB ben-wpan Driver");
5757+MODULE_LICENSE("GPL");
5758diff --git a/include/linux/if.h b/include/linux/if.h
5759index 3bc63e6..4fc7448 100644
5760--- a/include/linux/if.h
5761@@ -77,6 +77,8 @@
5762 #define IFF_OVS_DATAPATH 0x8000 /* device used as Open vSwitch
5763                      * datapath port */
5764
5765+#define IFF_IEEE802154_COORD 0x400 /* IEEE802.15.4 PAN coordinator */
5766+
5767 #define IF_GET_IFACE 0x0001 /* for querying only */
5768 #define IF_GET_PROTO 0x0002
5769
5770diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
5771index 6d722f4..47a57d8 100644
5772--- a/include/linux/if_arp.h
5773@@ -87,6 +87,8 @@
5774 #define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
5775 #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
5776 #define ARPHRD_IEEE802154 804
5777+#define ARPHRD_IEEE802154_MONITOR 805
5778+#define ARPHRD_SMAC 806 /* Freescale Simple MAC */
5779
5780 #define ARPHRD_PHONET 820 /* PhoNet media type */
5781 #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */
5782diff --git a/include/linux/if_ieee802154.h b/include/linux/if_ieee802154.h
5783new file mode 100644
5784index 0000000..cce32bb
5785--- /dev/null
5786@@ -0,0 +1,6 @@
5787+#ifndef __LINUX_IF_IEEE802154_H
5788+#define __LINUX_IF_IEEE802154_H
5789+
5790+#define IEEE802154_ALEN 8 /* size of 64-bit hardware address */
5791+
5792+#endif
5793diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
5794index 33d9f51..a379fc7 100644
5795--- a/include/linux/nl802154.h
5796@@ -68,14 +68,13 @@ enum {
5797     IEEE802154_ATTR_CHANNEL_PAGE_LIST,
5798
5799     IEEE802154_ATTR_PHY_NAME,
5800+ IEEE802154_ATTR_DEV_TYPE,
5801
5802     __IEEE802154_ATTR_MAX,
5803 };
5804
5805 #define IEEE802154_ATTR_MAX (__IEEE802154_ATTR_MAX - 1)
5806
5807-extern const struct nla_policy ieee802154_policy[];
5808-
5809 /* commands */
5810 /* REQ should be responded with CONF
5811  * and INDIC with RESP
5812@@ -126,4 +125,11 @@ enum {
5813
5814 #define IEEE802154_CMD_MAX (__IEEE802154_CMD_MAX - 1)
5815
5816+enum {
5817+ IEEE802154_DEV_WPAN,
5818+ IEEE802154_DEV_MONITOR,
5819+ IEEE802154_DEV_SMAC,
5820+ __IEEE802154_DEV_MAX,
5821+};
5822+
5823 #endif
5824diff --git a/include/linux/spi/at86rf230.h b/include/linux/spi/at86rf230.h
5825new file mode 100644
5826index 0000000..dff0225
5827--- /dev/null
5828@@ -0,0 +1,34 @@
5829+/*
5830+ * AT86RF230/RF231 driver
5831+ *
5832+ * Copyright (C) 2009 Siemens AG
5833+ *
5834+ * This program is free software; you can redistribute it and/or modify
5835+ * it under the terms of the GNU General Public License version 2
5836+ * as published by the Free Software Foundation.
5837+ *
5838+ * This program is distributed in the hope that it will be useful,
5839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5841+ * GNU General Public License for more details.
5842+ *
5843+ * You should have received a copy of the GNU General Public License along
5844+ * with this program; if not, write to the Free Software Foundation, Inc.,
5845+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5846+ *
5847+ * Written by:
5848+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
5849+ */
5850+#ifndef LINUX_SPI_AT86RF230_H
5851+#define LINUX_SPI_AT86RF230_H
5852+
5853+struct at86rf230_platform_data {
5854+ int rstn;
5855+ int slp_tr;
5856+ int dig2;
5857+ void (*reset)(void *reset_data);
5858+ void *reset_data;
5859+};
5860+
5861+#endif
5862+
5863diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
5864index 5743055..e12ce9a 100644
5865--- a/include/net/ieee802154_netdev.h
5866@@ -26,6 +26,8 @@
5867 #ifndef IEEE802154_NETDEVICE_H
5868 #define IEEE802154_NETDEVICE_H
5869
5870+#include <net/af_ieee802154.h>
5871+
5872 /*
5873  * A control block of skb passed between the ARPHRD_IEEE802154 device
5874  * and other stack parts.
5875@@ -81,7 +83,12 @@ struct wpan_phy;
5876  * get_phy should increment the reference counting on returned phy.
5877  * Use wpan_wpy_put to put that reference.
5878  */
5879+struct simple_mlme_ops {
5880+ struct wpan_phy *(*get_phy)(const struct net_device *dev);
5881+};
5882 struct ieee802154_mlme_ops {
5883+ struct simple_mlme_ops wpan_ops;
5884+
5885     int (*assoc_req)(struct net_device *dev,
5886             struct ieee802154_addr *addr,
5887             u8 channel, u8 page, u8 cap);
5888@@ -98,8 +105,6 @@ struct ieee802154_mlme_ops {
5889     int (*scan_req)(struct net_device *dev,
5890             u8 type, u32 channels, u8 page, u8 duration);
5891
5892- struct wpan_phy *(*get_phy)(const struct net_device *dev);
5893-
5894     /*
5895      * FIXME: these should become the part of PIB/MIB interface.
5896      * However we still don't have IB interface of any kind
5897@@ -110,12 +115,18 @@ struct ieee802154_mlme_ops {
5898     u8 (*get_bsn)(const struct net_device *dev);
5899 };
5900
5901-static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops(
5902+static inline struct simple_mlme_ops *simple_mlme_ops(
5903         const struct net_device *dev)
5904 {
5905     return dev->ml_priv;
5906 }
5907
5908+static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops(
5909+ const struct net_device *dev)
5910+{
5911+ return container_of(dev->ml_priv, struct ieee802154_mlme_ops, wpan_ops);
5912+}
5913+
5914 #endif
5915
5916
5917diff --git a/include/net/mac802154.h b/include/net/mac802154.h
5918new file mode 100644
5919index 0000000..df46f6a
5920--- /dev/null
5921@@ -0,0 +1,156 @@
5922+/*
5923+ * IEEE802.15.4-2003 specification
5924+ *
5925+ * Copyright (C) 2007, 2008 Siemens AG
5926+ *
5927+ * This program is free software; you can redistribute it and/or modify
5928+ * it under the terms of the GNU General Public License version 2
5929+ * as published by the Free Software Foundation.
5930+ *
5931+ * This program is distributed in the hope that it will be useful,
5932+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5933+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5934+ * GNU General Public License for more details.
5935+ *
5936+ * You should have received a copy of the GNU General Public License along
5937+ * with this program; if not, write to the Free Software Foundation, Inc.,
5938+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5939+ *
5940+ * Written by:
5941+ */
5942+#ifndef NET_MAC802154_H
5943+#define NET_MAC802154_H
5944+
5945+#include <linux/if_ieee802154.h>
5946+
5947+/**
5948+ * enum ieee802154_hw_addr_filt_flags - hardware flags
5949+ *
5950+ * These flags are used to indicate changed address settings from
5951+ * the stack to the hardware.
5952+ *
5953+ * @IEEE802515_SADDR_CHANGED:
5954+ * Indicates that the Short Address changed
5955+ *
5956+ * @IEEE802515_IEEEADDR_CHANGED:
5957+ * Indicates that the IEEE Address changed
5958+ *
5959+ * @IEEE802515_PANID_CHANGED:
5960+ * Indicates that the PAN ID changed
5961+ *
5962+ * @IEEE802515_PANC_CHANGED:
5963+ * Indicates that PAN Coordinator status changed
5964+ */
5965+enum ieee802154_hw_addr_filt_flags {
5966+ IEEE802515_SADDR_CHANGED = 1 << 0,
5967+ IEEE802515_IEEEADDR_CHANGED = 1 << 1,
5968+ IEEE802515_PANID_CHANGED = 1 << 2,
5969+ IEEE802515_PANC_CHANGED = 1 << 3,
5970+};
5971+
5972+struct ieee802154_hw_addr_filt {
5973+ u16 pan_id;
5974+ u16 short_addr;
5975+ u8 ieee_addr[IEEE802154_ALEN];
5976+ u8 pan_coord;
5977+};
5978+
5979+struct ieee802154_dev {
5980+ /* filled by the driver */
5981+ int extra_tx_headroom; /* headroom to reserve for tx skb */
5982+ u32 flags; /* Flags for device to set */
5983+ struct device *parent;
5984+
5985+ /* filled by mac802154 core */
5986+ struct ieee802154_hw_addr_filt hw_filt;
5987+ void *priv; /* driver-specific data */
5988+ struct wpan_phy *phy;
5989+};
5990+
5991+/* Checksum is in hardware and is omitted from packet */
5992+/**
5993+ * enum ieee802154_hw_flags - hardware flags
5994+ *
5995+ * These flags are used to indicate hardware capabilities to
5996+ * the stack. Generally, flags here should have their meaning
5997+ * done in a way that the simplest hardware doesn't need setting
5998+ * any particular flags. There are some exceptions to this rule,
5999+ * however, so you are advised to review these flags carefully.
6000+ *
6001+ * @IEEE802154_HW_OMIT_CKSUM:
6002+ * Indicates that receiver omits FCS and transmitter will add
6003+ * FCS on it's own.
6004+ *
6005+ * @IEEE802154_HW_AACK:
6006+ * Indicates that receiver will autorespond with ACK frames.
6007+ */
6008+enum ieee802154_hw_flags {
6009+ IEEE802154_HW_OMIT_CKSUM = 1 << 0,
6010+ IEEE802154_HW_AACK = 1 << 1,
6011+};
6012+
6013+struct sk_buff;
6014+
6015+/**
6016+ * struct ieee802154_ops - callbacks from mac802154 to the driver
6017+ *
6018+ * This structure contains various callbacks that the driver may
6019+ * handle or, in some cases, must handle, for example to transmit
6020+ * a frame.
6021+ *
6022+ * @start: Handler that 802.15.4 module calls for device initialisation.
6023+ * This function is called before the first interface is attached.
6024+ *
6025+ * @stop: Handler that 802.15.4 module calls for device cleanup
6026+ * This function is called after the last interface is removed.
6027+ *
6028+ * @xmit: Handler that 802.15.4 module calls for each transmitted frame.
6029+ * skb cntains the buffer starting from the IEEE 802.15.4 header.
6030+ * The low-level driver should send the frame based on available
6031+ * configuration.
6032+ * This function should return zero or negative errno.
6033+ * Called with pib_lock held.
6034+ *
6035+ * @ed: Handler that 802.15.4 module calls for Energy Detection.
6036+ * This function should place the value for detected energy
6037+ * (usually device-dependant) in the level pointer and return
6038+ * either zero or negative errno.
6039+ * Called with pib_lock held.
6040+ *
6041+ * @set_channel: Set radio for listening on specific channel.
6042+ * Set the device for listening on specified channel.
6043+ * Returns either zero, or negative errno.
6044+ * Called with pib_lock held.
6045+ *
6046+ * @set_hw_addr_filt: Set radio for listening on specific address.
6047+ * Set the device for listening on specified address.
6048+ * Returns either zero, or negative errno.
6049+ */
6050+struct ieee802154_ops {
6051+ struct module *owner;
6052+ int (*start)(struct ieee802154_dev *dev);
6053+ void (*stop)(struct ieee802154_dev *dev);
6054+ int (*xmit)(struct ieee802154_dev *dev,
6055+ struct sk_buff *skb);
6056+ int (*ed)(struct ieee802154_dev *dev, u8 *level);
6057+ int (*set_channel)(struct ieee802154_dev *dev,
6058+ int page,
6059+ int channel);
6060+ int (*set_hw_addr_filt)(struct ieee802154_dev *dev,
6061+ struct ieee802154_hw_addr_filt *filt,
6062+ unsigned long changed);
6063+ int (*ieee_addr)(struct ieee802154_dev *dev,
6064+ u8 addr[IEEE802154_ALEN]);
6065+};
6066+
6067+struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
6068+ struct ieee802154_ops *ops);
6069+int ieee802154_register_device(struct ieee802154_dev *dev);
6070+void ieee802154_unregister_device(struct ieee802154_dev *dev);
6071+void ieee802154_free_device(struct ieee802154_dev *dev);
6072+
6073+void ieee802154_rx(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi);
6074+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb,
6075+ u8 lqi);
6076+#endif
6077+
6078diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
6079index d86fffd..9e119c5 100644
6080--- a/include/net/wpan-phy.h
6081@@ -24,17 +24,19 @@
6082 #include <linux/netdevice.h>
6083 #include <linux/mutex.h>
6084
6085+#define WPAN_NUM_PAGES 32
6086+
6087 struct wpan_phy {
6088     struct mutex pib_lock;
6089
6090     /*
6091- * This is a PIB according to 802.15.4-2006.
6092+ * This is a PIB acording to 802.15.4-2006.
6093      * We do not provide timing-related variables, as they
6094      * aren't used outside of driver
6095      */
6096     u8 current_channel;
6097     u8 current_page;
6098- u32 channels_supported[32];
6099+ u32 channels_supported[WPAN_NUM_PAGES];
6100     u8 transmit_power;
6101     u8 cca_mode;
6102
6103@@ -42,7 +44,7 @@ struct wpan_phy {
6104     int idx;
6105
6106     struct net_device *(*add_iface)(struct wpan_phy *phy,
6107- const char *name);
6108+ const char *name, int type);
6109     void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
6110
6111     char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
6112diff --git a/net/Kconfig b/net/Kconfig
6113index 878151c..66271cc 100644
6114--- a/net/Kconfig
6115@@ -211,6 +211,8 @@ source "net/econet/Kconfig"
6116 source "net/wanrouter/Kconfig"
6117 source "net/phonet/Kconfig"
6118 source "net/ieee802154/Kconfig"
6119+source "net/mac802154/Kconfig"
6120+source "net/zigbee/Kconfig"
6121 source "net/sched/Kconfig"
6122 source "net/dcb/Kconfig"
6123 source "net/dns_resolver/Kconfig"
6124diff --git a/net/Makefile b/net/Makefile
6125index a51d946..b7a6585 100644
6126--- a/net/Makefile
6127@@ -60,6 +60,7 @@ ifneq ($(CONFIG_DCB),)
6128 obj-y += dcb/
6129 endif
6130 obj-$(CONFIG_IEEE802154) += ieee802154/
6131+obj-$(CONFIG_MAC802154) += mac802154/
6132
6133 ifeq ($(CONFIG_NET),y)
6134 obj-$(CONFIG_SYSCTL) += sysctl_net.o
6135diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
6136index 1c1de97..5f1a5af 100644
6137--- a/net/ieee802154/Kconfig
6138@@ -10,3 +10,12 @@ config IEEE802154
6139
6140       Say Y here to compile LR-WPAN support into the kernel or say M to
6141       compile it as modules.
6142+
6143+config IEEE802154_PROTO_DEBUG
6144+ bool "IEEE 802.15.4 protocol stack debugging messages"
6145+ depends on IEEE802154
6146+ default y
6147+ help
6148+ Say Y here to make the IEEE 802.15.4 protocol stack generate
6149+ extensive debugging messages.
6150+
6151diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
6152index 5761185..53f1ec3 100644
6153--- a/net/ieee802154/Makefile
6154@@ -1,3 +1,6 @@
6155 obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
6156 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
6157 af_802154-y := af_ieee802154.o raw.o dgram.o
6158+
6159+ccflags-$(CONFIG_IEEE802154_PROTO_DEBUG) += -DDEBUG
6160+ccflags-y += -Wall
6161diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
6162index 1a3334c..5c69833 100644
6163--- a/net/ieee802154/dgram.c
6164@@ -130,8 +130,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
6165     switch (cmd) {
6166     case SIOCOUTQ:
6167     {
6168- int amount = sk_wmem_alloc_get(sk);
6169-
6170+ int amount = atomic_read(&sk->sk_wmem_alloc);
6171         return put_user(amount, (int __user *)arg);
6172     }
6173
6174diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
6175index aadec42..e78d6c6 100644
6176--- a/net/ieee802154/ieee802154.h
6177@@ -21,6 +21,10 @@
6178 int __init ieee802154_nl_init(void);
6179 void __exit ieee802154_nl_exit(void);
6180
6181+#include <net/netlink.h>
6182+
6183+extern const struct nla_policy ieee802154_policy[];
6184+
6185 #define IEEE802154_OP(_cmd, _func) \
6186     { \
6187         .cmd = _cmd, \
6188diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
6189index 71ee110..51e375e 100644
6190--- a/net/ieee802154/nl-mac.c
6191@@ -262,7 +262,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
6192     if (!hdr)
6193         goto out;
6194
6195- phy = ieee802154_mlme_ops(dev)->get_phy(dev);
6196+ phy = simple_mlme_ops(dev)->get_phy(dev);
6197     BUG_ON(!phy);
6198
6199     NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
6200diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
6201index 02548b2..49a29d7 100644
6202--- a/net/ieee802154/nl-phy.c
6203@@ -24,6 +24,7 @@
6204
6205 #include <linux/kernel.h>
6206 #include <linux/slab.h>
6207+#include <linux/if_arp.h>
6208 #include <net/netlink.h>
6209 #include <net/genetlink.h>
6210 #include <net/wpan-phy.h>
6211@@ -44,7 +45,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
6212     pr_debug("%s\n", __func__);
6213
6214     if (!buf)
6215- return -EMSGSIZE;
6216+ goto out;
6217
6218     hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
6219         IEEE802154_LIST_PHY);
6220@@ -56,7 +57,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
6221
6222     NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page);
6223     NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel);
6224- for (i = 0; i < 32; i++) {
6225+ for (i = 0; i < WPAN_NUM_PAGES; i++) {
6226         if (phy->channels_supported[i])
6227             buf[pages++] = phy->channels_supported[i] | (i << 27);
6228     }
6229@@ -65,7 +66,6 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
6230                 pages * sizeof(uint32_t), buf);
6231
6232     mutex_unlock(&phy->pib_lock);
6233- kfree(buf);
6234     return genlmsg_end(msg, hdr);
6235
6236 nla_put_failure:
6237@@ -178,6 +178,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
6238     const char *devname;
6239     int rc = -ENOBUFS;
6240     struct net_device *dev;
6241+ int type = IEEE802154_DEV_WPAN;
6242
6243     pr_debug("%s\n", __func__);
6244
6245@@ -192,7 +193,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
6246         devname = nla_data(info->attrs[IEEE802154_ATTR_DEV_NAME]);
6247         if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1]
6248                 != '\0')
6249- return -EINVAL; /* phy name should be null-terminated */
6250+ return -EINVAL; /* dev name should be null-terminated */
6251     } else {
6252         devname = "wpan%d";
6253     }
6254@@ -200,6 +201,19 @@ static int ieee802154_add_iface(struct sk_buff *skb,
6255     if (strlen(devname) >= IFNAMSIZ)
6256         return -ENAMETOOLONG;
6257
6258+ if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
6259+ nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
6260+ IEEE802154_ADDR_LEN) {
6261+ return -EINVAL;
6262+ }
6263+
6264+ if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) {
6265+ type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]);
6266+ if (type > __IEEE802154_DEV_MAX) {
6267+ return -EINVAL;
6268+ }
6269+ }
6270+
6271     phy = wpan_phy_find(name);
6272     if (!phy)
6273         return -ENODEV;
6274@@ -213,12 +227,29 @@ static int ieee802154_add_iface(struct sk_buff *skb,
6275         goto nla_put_failure;
6276     }
6277
6278- dev = phy->add_iface(phy, devname);
6279+ dev = phy->add_iface(phy, devname, type);
6280     if (IS_ERR(dev)) {
6281         rc = PTR_ERR(dev);
6282         goto nla_put_failure;
6283     }
6284
6285+ if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
6286+ struct sockaddr addr;
6287+
6288+ addr.sa_family = ARPHRD_IEEE802154;
6289+ nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR], IEEE802154_ADDR_LEN);
6290+
6291+ /*
6292+ * strangely enough, some callbacks (inetdev_event) from
6293+ * dev_set_mac_address require RTNL_LOCK
6294+ */
6295+ rtnl_lock();
6296+ rc = dev_set_mac_address(dev, &addr);
6297+ rtnl_unlock();
6298+ if (rc)
6299+ goto dev_unregister;
6300+ }
6301+
6302     NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
6303     NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
6304
6305@@ -228,6 +259,11 @@ static int ieee802154_add_iface(struct sk_buff *skb,
6306
6307     return ieee802154_nl_reply(msg, info);
6308
6309+dev_unregister:
6310+ rtnl_lock(); /* del_iface must be called with RTNL lock */
6311+ phy->del_iface(phy, dev);
6312+ dev_put(dev);
6313+ rtnl_unlock();
6314 nla_put_failure:
6315     nlmsg_free(msg);
6316 out_dev:
6317@@ -257,7 +293,7 @@ static int ieee802154_del_iface(struct sk_buff *skb,
6318     if (!dev)
6319         return -ENODEV;
6320
6321- phy = ieee802154_mlme_ops(dev)->get_phy(dev);
6322+ phy = simple_mlme_ops(dev)->get_phy(dev);
6323     BUG_ON(!phy);
6324
6325     rc = -EINVAL;
6326diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
6327index 6adda4d..235cd65 100644
6328--- a/net/ieee802154/nl_policy.c
6329@@ -28,6 +28,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
6330     [IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, },
6331     [IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, },
6332     [IEEE802154_ATTR_PHY_NAME] = { .type = NLA_STRING, },
6333+ [IEEE802154_ATTR_DEV_TYPE] = { .type = NLA_U8, },
6334
6335     [IEEE802154_ATTR_STATUS] = { .type = NLA_U8, },
6336     [IEEE802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
6337diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
6338index 1627ef2..380fe1a 100644
6339--- a/net/ieee802154/wpan-class.c
6340@@ -56,7 +56,7 @@ static ssize_t channels_supported_show(struct device *dev,
6341     int i, len = 0;
6342
6343     mutex_lock(&phy->pib_lock);
6344- for (i = 0; i < 32; i++) {
6345+ for (i = 0; i < WPAN_NUM_PAGES; i++) {
6346         ret = snprintf(buf + len, PAGE_SIZE - len,
6347                 "%#09x\n", phy->channels_supported[i]);
6348         if (ret < 0)
6349diff --git a/net/mac802154/Kconfig b/net/mac802154/Kconfig
6350new file mode 100644
6351index 0000000..32e63bc
6352--- /dev/null
6353@@ -0,0 +1,24 @@
6354+config MAC802154
6355+ tristate "Generic IEEE 802.15.4 Soft Networking Stack (mac802154)"
6356+ depends on IEEE802154 && EXPERIMENTAL
6357+ select CRC_CCITT
6358+ ---help---
6359+ This option enables the hardware independent IEEE 802.15.4
6360+ networking stack for SoftMAC devices (the ones implementing
6361+ only PHY level of IEEE 802.15.4 standard).
6362+
6363+ Note: this implementation is neither certified, nor feature
6364+ complete! We do not guarantee that it is compatible w/ other
6365+ implementations, etc.
6366+
6367+ If you plan to use HardMAC IEEE 802.15.4 devices, you can
6368+ say N here. Alternatievly you can say M to compile it as
6369+ module.
6370+
6371+config MAC802154_DEBUG
6372+ bool "IEEE 802.15.4 SoftMAC debugging messages"
6373+ depends on MAC802154
6374+ default y
6375+ help
6376+ Say Y here to make the IEEE 802.15.4 SoftMAC generate extensive
6377+ debugging messages.
6378diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
6379new file mode 100644
6380index 0000000..d76fabb
6381--- /dev/null
6382@@ -0,0 +1,6 @@
6383+obj-$(CONFIG_MAC802154) += mac802154.o
6384+mac802154-objs := rx.o tx.o main.o monitor.o wpan.o mac_cmd.o scan.o mib.o \
6385+ beacon.o beacon_hash.o smac.o
6386+
6387+ccflags-$(CONFIG_MAC802154_DEBUG) += -DDEBUG
6388+ccflags-y += -Wall
6389diff --git a/net/mac802154/beacon.c b/net/mac802154/beacon.c
6390new file mode 100644
6391index 0000000..6b0d327
6392--- /dev/null
6393@@ -0,0 +1,282 @@
6394+/*
6395+ * MAC beacon interface
6396+ *
6397+ * Copyright 2007, 2008 Siemens AG
6398+ *
6399+ * This program is free software; you can redistribute it and/or modify
6400+ * it under the terms of the GNU General Public License version 2
6401+ * as published by the Free Software Foundation.
6402+ *
6403+ * This program is distributed in the hope that it will be useful,
6404+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6405+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6406+ * GNU General Public License for more details.
6407+ *
6408+ * You should have received a copy of the GNU General Public License along
6409+ * with this program; if not, write to the Free Software Foundation, Inc.,
6410+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6411+ *
6412+ * Written by:
6413+ * Sergey Lapin <slapin@ossfans.org>
6414+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6415+ */
6416+
6417+#include <linux/kernel.h>
6418+#include <linux/slab.h>
6419+#include <linux/if_arp.h>
6420+#include <linux/list.h>
6421+
6422+#include <net/af_ieee802154.h>
6423+#include <net/nl802154.h>
6424+#include <net/mac802154.h>
6425+#include <net/ieee802154.h>
6426+#include <net/ieee802154_netdev.h>
6427+
6428+#include "mac802154.h"
6429+#include "beacon_hash.h"
6430+
6431+/* Beacon frame format per specification is the followinf:
6432+ * Standard MAC frame header:
6433+ * FC (2) SEQ (1)
6434+ * Addressing (4-20)
6435+ * Beacon fields:
6436+ * <Superframe specification> (2)
6437+ * <GTS> (?)
6438+ * <Pending address> (?)
6439+ * <Beacon payload> (?)
6440+ * FCS (2)
6441+ *
6442+ * Superframe specification:
6443+ * bit Value
6444+ * 15 Association permit
6445+ * 14 PAN coordinator
6446+ * 13 Reserved
6447+ * 12 Battery life extension
6448+ * 8-11 Final CAP slot
6449+ * 4-7 Superframe order
6450+ * 0-3 Beacon order
6451+ *
6452+ * GTS:
6453+ * <GTS specification> (1)
6454+ * <GTS directions> (0-1)
6455+ * <GTS list> (?)
6456+ *
6457+ * Pending address:
6458+ * <Pending address specification> (1)
6459+ * <Pending address list (?)
6460+ *
6461+ * GTS specification:
6462+ * bit Value
6463+ * 7 GTS permit
6464+ * 3-6 Reserved
6465+ * 0-2 GTS descriptor count
6466+ *
6467+ * Pending address specification:
6468+ * bit Value
6469+ * 7 Reserved
6470+ * 4-6 Number of extended addresses pendinf
6471+ * 3 Reserved
6472+ * 0-2 Number of short addresses pending
6473+ * */
6474+
6475+#define IEEE802154_BEACON_SF_BO_BEACONLESS (15 << 0)
6476+#define IEEE802154_BEACON_SF_SO(x) ((x & 0xf) << 4)
6477+#define IEEE802154_BEACON_SF_SO_INACTIVE IEEE802154_BEACON_SF_SO(15)
6478+#define IEEE802154_BEACON_SF_PANCOORD (1 << 14)
6479+#define IEEE802154_BEACON_SF_CANASSOC (1 << 15)
6480+#define IEEE802154_BEACON_GTS_COUNT(x) (x << 0)
6481+#define IEEE802154_BEACON_GTS_PERMIT (1 << 7)
6482+#define IEEE802154_BEACON_PA_SHORT(x) ((x & 7) << 0)
6483+#define IEEE802154_BEACON_PA_LONG(x) ((x & 7) << 4)
6484+
6485+/* Flags parameter */
6486+#define IEEE802154_BEACON_FLAG_PANCOORD (1 << 0)
6487+#define IEEE802154_BEACON_FLAG_CANASSOC (1 << 1)
6488+#define IEEE802154_BEACON_FLAG_GTSPERMIT (1 << 2)
6489+
6490+struct mac802154_address_list {
6491+ struct list_head list;
6492+ struct ieee802154_addr addr;
6493+};
6494+
6495+/* Per spec; optimizations are needed */
6496+struct mac802154_pandsc {
6497+ struct list_head list;
6498+ struct ieee802154_addr addr; /* Contains panid */
6499+ int channel;
6500+ u16 sf;
6501+ bool gts_permit;
6502+ u8 lqi;
6503+/* FIXME: Aging of stored PAN descriptors is not decided yet,
6504+ * because no PAN descriptor storage is implemented yet */
6505+ u32 timestamp;
6506+};
6507+
6508+/*
6509+ * @dev device
6510+ * @addr destination address
6511+ * @saddr source address
6512+ * @buf beacon payload
6513+ * @len beacon payload size
6514+ * @pan_coord - if we're PAN coordinator while sending this frame
6515+ * @gts_permit - wheather we allow GTS requests
6516+ * @al address list to be provided in beacon
6517+ *
6518+ * TODO:
6519+ * For a beacon frame, the sequence number field shall specify a BSN.
6520+ * Each coordinator shall store its current
6521+ * BSN value in the MAC PIB attribute macBSN and initialize it to
6522+ * a random value.
6523+ * The algorithm for choosing a random number is out of the scope
6524+ * of this standard. The coordinator shall copy the value of the macBSN
6525+ * attribute into the sequence number field of a beacon frame,
6526+ * each time one is generated, and shall then increment macBSN by one.
6527+ *
6528+*/
6529+
6530+
6531+int mac802154_send_beacon(struct net_device *dev,
6532+ struct ieee802154_addr *saddr,
6533+ u16 pan_id, const u8 *buf, int len,
6534+ int flags, struct list_head *al)
6535+{
6536+ struct sk_buff *skb;
6537+ int err;
6538+ u16 sf;
6539+ u8 gts;
6540+ u8 pa_spec;
6541+ int addr16_cnt;
6542+ int addr64_cnt;
6543+ struct ieee802154_addr addr;
6544+
6545+ BUG_ON(dev->type != ARPHRD_IEEE802154);
6546+
6547+ skb = alloc_skb(LL_ALLOCATED_SPACE(dev) + len, GFP_ATOMIC);
6548+ if (!skb)
6549+ return -ENOMEM;
6550+
6551+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
6552+
6553+ skb_reset_network_header(skb);
6554+
6555+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_BEACON;
6556+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_bsn(dev);
6557+
6558+ addr.addr_type = IEEE802154_ADDR_NONE;
6559+ err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &addr, saddr, len);
6560+ if (err < 0) {
6561+ kfree_skb(skb);
6562+ return err;
6563+ }
6564+ skb_reset_mac_header(skb);
6565+
6566+ /* Superframe */
6567+ sf = IEEE802154_BEACON_SF_BO_BEACONLESS;
6568+ sf |= IEEE802154_BEACON_SF_SO_INACTIVE;
6569+ if (flags & IEEE802154_BEACON_FLAG_PANCOORD)
6570+ sf |= IEEE802154_BEACON_SF_PANCOORD;
6571+
6572+ if (flags & IEEE802154_BEACON_FLAG_CANASSOC)
6573+ sf |= IEEE802154_BEACON_SF_CANASSOC;
6574+ memcpy(skb_put(skb, sizeof(sf)), &sf, sizeof(sf));
6575+
6576+ /* TODO GTS */
6577+ gts = 0;
6578+
6579+ if (flags & IEEE802154_BEACON_FLAG_GTSPERMIT)
6580+ gts |= IEEE802154_BEACON_GTS_PERMIT;
6581+ memcpy(skb_put(skb, sizeof(gts)), &gts, sizeof(gts));
6582+
6583+ /* FIXME pending address */
6584+ addr16_cnt = 0;
6585+ addr64_cnt = 0;
6586+
6587+ pa_spec = IEEE802154_BEACON_PA_LONG(addr64_cnt) |
6588+ IEEE802154_BEACON_PA_SHORT(addr16_cnt);
6589+ memcpy(skb_put(skb, sizeof(pa_spec)), &pa_spec, sizeof(pa_spec));
6590+
6591+ memcpy(skb_put(skb, len), buf, len);
6592+
6593+ skb->dev = dev;
6594+ skb->protocol = htons(ETH_P_IEEE802154);
6595+
6596+ return dev_queue_xmit(skb);
6597+}
6598+
6599+/* at entry to this function we need skb->data to point to start
6600+ * of beacon field and MAC frame already parsed into MAC_CB */
6601+
6602+static int parse_beacon_frame(struct sk_buff *skb, u8 *buf,
6603+ int *flags, struct list_head *al)
6604+{
6605+ int offt = 0;
6606+ u8 gts_spec;
6607+ u8 pa_spec;
6608+ struct mac802154_pandsc *pd;
6609+ u16 sf = skb->data[0] + (skb->data[1] << 8);
6610+
6611+ pd = kzalloc(sizeof(struct mac802154_pandsc), GFP_KERNEL);
6612+
6613+ /* Filling-up pre-parsed values */
6614+ pd->lqi = mac_cb(skb)->lqi;
6615+ pd->sf = sf;
6616+ /* FIXME: make sure we do it right */
6617+ memcpy(&pd->addr, &mac_cb(skb)->da, sizeof(struct ieee802154_addr));
6618+
6619+ /* Supplying our nitifiers with data */
6620+ ieee802154_nl_beacon_indic(skb->dev, pd->addr.pan_id,
6621+ pd->addr.short_addr);
6622+ /* FIXME: We don't cache PAN descriptors yet */
6623+ kfree(pd);
6624+
6625+ offt += 2;
6626+ gts_spec = skb->data[offt++];
6627+ /* FIXME !!! */
6628+ if ((gts_spec & 7) != 0) {
6629+ pr_debug("We still don't parse GTS part properly");
6630+ return -ENOTSUPP;
6631+ }
6632+ pa_spec = skb->data[offt++];
6633+ /* FIXME !!! */
6634+ if (pa_spec != 0) {
6635+ pr_debug("We still don't parse PA part properly");
6636+ return -ENOTSUPP;
6637+ }
6638+
6639+ *flags = 0;
6640+
6641+ if (sf & IEEE802154_BEACON_SF_PANCOORD)
6642+ *flags |= IEEE802154_BEACON_FLAG_PANCOORD;
6643+
6644+ if (sf & IEEE802154_BEACON_SF_CANASSOC)
6645+ *flags |= IEEE802154_BEACON_FLAG_CANASSOC;
6646+ BUG_ON(skb->len - offt < 0);
6647+ /* FIXME */
6648+ if (buf && (skb->len - offt > 0))
6649+ memcpy(buf, skb->data + offt, skb->len - offt);
6650+ return 0;
6651+}
6652+
6653+int mac802154_process_beacon(struct net_device *dev,
6654+ struct sk_buff *skb)
6655+{
6656+ int flags;
6657+ int ret;
6658+ ret = parse_beacon_frame(skb, NULL, &flags, NULL);
6659+
6660+ /* Here we have cb->sa = coordinator address, and PAN address */
6661+
6662+ if (ret < 0) {
6663+ ret = NET_RX_DROP;
6664+ goto fail;
6665+ }
6666+ dev_dbg(&dev->dev, "got beacon from pan %04x\n",
6667+ mac_cb(skb)->sa.pan_id);
6668+ mac802154_beacon_hash_add(&mac_cb(skb)->sa);
6669+ mac802154_beacon_hash_dump();
6670+ ret = NET_RX_SUCCESS;
6671+fail:
6672+ kfree_skb(skb);
6673+ return ret;
6674+}
6675+
6676diff --git a/net/mac802154/beacon_hash.c b/net/mac802154/beacon_hash.c
6677new file mode 100644
6678index 0000000..97fb987
6679--- /dev/null
6680@@ -0,0 +1,106 @@
6681+/*
6682+ * MAC beacon hash storage
6683+ *
6684+ * Copyright 2007, 2008 Siemens AG
6685+ *
6686+ * This program is free software; you can redistribute it and/or modify
6687+ * it under the terms of the GNU General Public License version 2
6688+ * as published by the Free Software Foundation.
6689+ *
6690+ * This program is distributed in the hope that it will be useful,
6691+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6692+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6693+ * GNU General Public License for more details.
6694+ *
6695+ * You should have received a copy of the GNU General Public License along
6696+ * with this program; if not, write to the Free Software Foundation, Inc.,
6697+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6698+ *
6699+ * Written by:
6700+ * Sergey Lapin <slapin@ossfans.org>
6701+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6702+ */
6703+
6704+#include <linux/slab.h>
6705+#include <linux/list.h>
6706+#include <linux/spinlock.h>
6707+
6708+#include <net/af_ieee802154.h>
6709+
6710+#include "beacon_hash.h"
6711+
6712+static struct hlist_head beacon_hash[IEEE802154_BEACON_HTABLE_SIZE];
6713+static DEFINE_SPINLOCK(beacon_hash_lock);
6714+
6715+static int beacon_hashfn(struct ieee802154_addr *coord_addr, u16 pan_addr)
6716+{
6717+ return pan_addr % IEEE802154_BEACON_HTABLE_SIZE;
6718+}
6719+
6720+static void __beacon_add_node(struct ieee802154_addr *coord_addr, u16 pan_addr)
6721+{
6722+ struct beacon_node *node =
6723+ kzalloc(sizeof(struct beacon_node), GFP_KERNEL);
6724+ struct hlist_head *list =
6725+ &beacon_hash[beacon_hashfn(coord_addr, pan_addr)];
6726+ memcpy(&node->coord_addr, coord_addr, sizeof(struct ieee802154_addr));
6727+ node->pan_addr = pan_addr;
6728+ INIT_HLIST_NODE(&node->list);
6729+ hlist_add_head(&node->list, list);
6730+}
6731+
6732+struct beacon_node *mac802154_beacon_find_pan(
6733+ struct ieee802154_addr *coord_addr, u16 pan_addr)
6734+{
6735+ struct hlist_head *list;
6736+ struct hlist_node *tmp;
6737+ list = &beacon_hash[beacon_hashfn(coord_addr, pan_addr)];
6738+ if (hlist_empty(list))
6739+ return NULL;
6740+ hlist_for_each(tmp, list) {
6741+ struct beacon_node *entry =
6742+ hlist_entry(tmp, struct beacon_node, list);
6743+ if (entry->pan_addr == pan_addr)
6744+ return entry;
6745+ }
6746+ return NULL;
6747+}
6748+
6749+void mac802154_beacon_hash_add(struct ieee802154_addr *coord_addr)
6750+{
6751+ if (!mac802154_beacon_find_pan(coord_addr, coord_addr->pan_id)) {
6752+ spin_lock(&beacon_hash_lock);
6753+ __beacon_add_node(coord_addr, coord_addr->pan_id);
6754+ spin_unlock(&beacon_hash_lock);
6755+ }
6756+}
6757+
6758+void mac802154_beacon_hash_del(struct ieee802154_addr *coord_addr)
6759+{
6760+ struct beacon_node *entry = mac802154_beacon_find_pan(coord_addr,
6761+ coord_addr->pan_id);
6762+ if (!entry)
6763+ return;
6764+ spin_lock(&beacon_hash_lock);
6765+ hlist_del(&entry->list);
6766+ spin_unlock(&beacon_hash_lock);
6767+ kfree(entry);
6768+}
6769+
6770+void mac802154_beacon_hash_dump(void)
6771+{
6772+ int i;
6773+ struct hlist_node *tmp;
6774+ pr_debug("beacon hash dump begin\n");
6775+ spin_lock(&beacon_hash_lock);
6776+ for (i = 0; i < IEEE802154_BEACON_HTABLE_SIZE; i++) {
6777+ struct beacon_node *entry;
6778+ hlist_for_each(tmp, &beacon_hash[i]) {
6779+ entry = hlist_entry(tmp, struct beacon_node, list);
6780+ pr_debug("PAN: %04x\n", entry->pan_addr);
6781+ }
6782+ }
6783+ spin_unlock(&beacon_hash_lock);
6784+ pr_debug("beacon hash dump end\n");
6785+}
6786+
6787diff --git a/net/mac802154/beacon_hash.h b/net/mac802154/beacon_hash.h
6788new file mode 100644
6789index 0000000..a732aa5
6790--- /dev/null
6791@@ -0,0 +1,41 @@
6792+/*
6793+ * MAC beacon hash storage
6794+ *
6795+ * Copyright 2007, 2008 Siemens AG
6796+ *
6797+ * This program is free software; you can redistribute it and/or modify
6798+ * it under the terms of the GNU General Public License version 2
6799+ * as published by the Free Software Foundation.
6800+ *
6801+ * This program is distributed in the hope that it will be useful,
6802+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6803+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6804+ * GNU General Public License for more details.
6805+ *
6806+ * You should have received a copy of the GNU General Public License along
6807+ * with this program; if not, write to the Free Software Foundation, Inc.,
6808+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6809+ *
6810+ * Written by:
6811+ * Sergey Lapin <slapin@ossfans.org>
6812+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6813+ */
6814+
6815+#ifndef IEEE802154_BEACON_HASH_H
6816+#define IEEE802154_BEACON_HASH_H
6817+
6818+#define IEEE802154_BEACON_HTABLE_SIZE 256
6819+
6820+struct beacon_node {
6821+ struct hlist_node list;
6822+ struct ieee802154_addr coord_addr;
6823+ u16 pan_addr;
6824+};
6825+struct beacon_node *mac802154_beacon_find_pan(
6826+ struct ieee802154_addr *coord_addr,
6827+ u16 pan_addr);
6828+void mac802154_beacon_hash_add(struct ieee802154_addr *coord_addr);
6829+void mac802154_beacon_hash_del(struct ieee802154_addr *coord_addr);
6830+void mac802154_beacon_hash_dump(void);
6831+#endif
6832+
6833diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
6834new file mode 100644
6835index 0000000..f35245d
6836--- /dev/null
6837@@ -0,0 +1,126 @@
6838+/*
6839+ * Copyright (C) 2007, 2008, 2009 Siemens AG
6840+ *
6841+ * This program is free software; you can redistribute it and/or modify
6842+ * it under the terms of the GNU General Public License version 2
6843+ * as published by the Free Software Foundation.
6844+ *
6845+ * This program is distributed in the hope that it will be useful,
6846+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6847+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6848+ * GNU General Public License for more details.
6849+ *
6850+ * You should have received a copy of the GNU General Public License along
6851+ * with this program; if not, write to the Free Software Foundation, Inc.,
6852+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6853+ *
6854+ * Written by:
6855+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
6856+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
6857+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6858+ */
6859+#ifndef MAC802154_H
6860+#define MAC802154_H
6861+
6862+#include <linux/spinlock.h>
6863+
6864+struct mac802154_priv {
6865+ struct ieee802154_dev hw;
6866+ struct ieee802154_ops *ops;
6867+
6868+ struct wpan_phy *phy;
6869+
6870+ int open_count;
6871+ /* As in mac80211 slaves list is modified:
6872+ * 1) under the RTNL
6873+ * 2) protected by slaves_mtx;
6874+ * 3) in an RCU manner
6875+ *
6876+ * So atomic readers can use any of this protection methods
6877+ */
6878+ struct list_head slaves;
6879+ struct mutex slaves_mtx;
6880+ /* This one is used for scanning and other
6881+ * jobs not to be interfered with serial driver */
6882+ struct workqueue_struct *dev_workqueue;
6883+
6884+ /*
6885+ * These flags are also modified under slaves_mtx and RTNL,
6886+ * so you can read them using any of protection methods.
6887+ */
6888+ /* SoftMAC device is registered and running. One can add subinterfaces. */
6889+ unsigned running: 1;
6890+};
6891+
6892+#define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw)
6893+
6894+struct mac802154_wpan_mib {
6895+ spinlock_t mib_lock;
6896+
6897+ u16 pan_id;
6898+ u16 short_addr;
6899+
6900+ u8 chan;
6901+ u8 page;
6902+
6903+ /* MAC BSN field */
6904+ u8 bsn;
6905+ /* MAC BSN field */
6906+ u8 dsn;
6907+};
6908+
6909+struct mac802154_sub_if_data {
6910+ struct list_head list; /* the ieee802154_priv->slaves list */
6911+
6912+ struct mac802154_priv *hw;
6913+ struct net_device *dev;
6914+
6915+ int type;
6916+
6917+ spinlock_t mib_lock;
6918+
6919+ u16 pan_id;
6920+ u16 short_addr;
6921+
6922+ u8 chan;
6923+ u8 page;
6924+
6925+ /* MAC BSN field */
6926+ u8 bsn;
6927+ /* MAC DSN field */
6928+ u8 dsn;
6929+};
6930+
6931+struct ieee802154_addr;
6932+
6933+extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
6934+extern struct simple_mlme_ops mac802154_mlme_simple;
6935+
6936+int mac802154_mlme_scan_req(struct net_device *dev,
6937+ u8 type, u32 channels, u8 page, u8 duration);
6938+
6939+int mac802154_process_cmd(struct net_device *dev, struct sk_buff *skb);
6940+int mac802154_process_beacon(struct net_device *dev, struct sk_buff *skb);
6941+int mac802154_send_beacon(struct net_device *dev,
6942+ struct ieee802154_addr *saddr,
6943+ u16 pan_id, const u8 *buf, int len,
6944+ int flags, struct list_head *al);
6945+int mac802154_send_beacon_req(struct net_device *dev);
6946+
6947+struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev);
6948+
6949+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6950+void mac802154_monitor_setup(struct net_device *dev);
6951+
6952+void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6953+void mac802154_smac_setup(struct net_device *dev);
6954+
6955+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6956+void mac802154_wpan_setup(struct net_device *dev);
6957+
6958+int mac802154_slave_open(struct net_device *dev);
6959+int mac802154_slave_close(struct net_device *dev);
6960+
6961+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
6962+ u8 page, u8 chan);
6963+#endif
6964diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
6965new file mode 100644
6966index 0000000..c763585
6967--- /dev/null
6968@@ -0,0 +1,362 @@
6969+/*
6970+ * MAC commands interface
6971+ *
6972+ * Copyright 2007, 2008 Siemens AG
6973+ *
6974+ * This program is free software; you can redistribute it and/or modify
6975+ * it under the terms of the GNU General Public License version 2
6976+ * as published by the Free Software Foundation.
6977+ *
6978+ * This program is distributed in the hope that it will be useful,
6979+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6980+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6981+ * GNU General Public License for more details.
6982+ *
6983+ * You should have received a copy of the GNU General Public License along
6984+ * with this program; if not, write to the Free Software Foundation, Inc.,
6985+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6986+ *
6987+ * Written by:
6988+ * Sergey Lapin <slapin@ossfans.org>
6989+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6990+ */
6991+
6992+#include <linux/kernel.h>
6993+#include <linux/skbuff.h>
6994+#include <linux/if_arp.h>
6995+#include <net/af_ieee802154.h>
6996+#include <net/mac802154.h>
6997+#include <net/ieee802154.h>
6998+#include <net/ieee802154_netdev.h>
6999+#include <net/nl802154.h>
7000+
7001+#include "mac802154.h"
7002+#include "mib.h"
7003+
7004+static int mac802154_cmd_beacon_req(struct sk_buff *skb)
7005+{
7006+ struct ieee802154_addr saddr; /* jeez */
7007+ int flags = 0;
7008+ u16 shortaddr;
7009+
7010+ if (skb->len != 1)
7011+ return -EINVAL;
7012+
7013+ if (skb->pkt_type != PACKET_BROADCAST)
7014+ return 0;
7015+
7016+ /* Checking if we're really PAN coordinator
7017+ * before sending beacons */
7018+ if (!(skb->dev->priv_flags & IFF_IEEE802154_COORD))
7019+ return 0;
7020+
7021+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE ||
7022+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_SHORT ||
7023+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST ||
7024+ mac_cb(skb)->da.short_addr != IEEE802154_ADDR_BROADCAST)
7025+ return -EINVAL;
7026+
7027+ shortaddr = mac802154_dev_get_short_addr(skb->dev);
7028+ if (shortaddr != IEEE802154_ADDR_BROADCAST &&
7029+ shortaddr != IEEE802154_ADDR_UNDEF) {
7030+ saddr.addr_type = IEEE802154_ADDR_SHORT;
7031+ saddr.short_addr = shortaddr;
7032+ } else {
7033+ saddr.addr_type = IEEE802154_ADDR_LONG;
7034+ memcpy(saddr.hwaddr, skb->dev->dev_addr, IEEE802154_ADDR_LEN);
7035+ }
7036+ saddr.pan_id = mac802154_dev_get_pan_id(skb->dev);
7037+
7038+
7039+ /* 7 bytes of MHR and 1 byte of command frame identifier
7040+ * We have no information in this command to proceed with.
7041+ * we need to submit beacon as answer to this. */
7042+
7043+ return mac802154_send_beacon(skb->dev, &saddr,
7044+ ieee802154_mlme_ops(skb->dev)->get_pan_id(skb->dev),
7045+ NULL, 0, flags, NULL);
7046+}
7047+
7048+static int mac802154_cmd_assoc_req(struct sk_buff *skb)
7049+{
7050+ u8 cap;
7051+
7052+ if (skb->len != 2)
7053+ return -EINVAL;
7054+
7055+ if (skb->pkt_type != PACKET_HOST)
7056+ return 0;
7057+
7058+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
7059+ mac_cb(skb)->sa.pan_id != IEEE802154_PANID_BROADCAST)
7060+ return -EINVAL;
7061+
7062+ /*
7063+ * FIXME: check that we allow incoming ASSOC requests
7064+ * by consulting MIB
7065+ */
7066+
7067+ cap = skb->data[1];
7068+
7069+ return ieee802154_nl_assoc_indic(skb->dev, &mac_cb(skb)->sa, cap);
7070+}
7071+
7072+static int mac802154_cmd_assoc_resp(struct sk_buff *skb)
7073+{
7074+ u8 status;
7075+ u16 short_addr;
7076+
7077+ if (skb->len != 4)
7078+ return -EINVAL;
7079+
7080+ if (skb->pkt_type != PACKET_HOST)
7081+ return 0;
7082+
7083+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
7084+ mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
7085+ !(mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN))
7086+ return -EINVAL;
7087+
7088+ /* FIXME: check that we requested association ? */
7089+
7090+ status = skb->data[3];
7091+ short_addr = skb->data[1] | (skb->data[2] << 8);
7092+ pr_info("Received ASSOC-RESP status %x, addr %hx\n", status,
7093+ short_addr);
7094+ if (status) {
7095+ mac802154_dev_set_short_addr(skb->dev,
7096+ IEEE802154_ADDR_BROADCAST);
7097+ mac802154_dev_set_pan_id(skb->dev,
7098+ IEEE802154_PANID_BROADCAST);
7099+ } else
7100+ mac802154_dev_set_short_addr(skb->dev, short_addr);
7101+
7102+ return ieee802154_nl_assoc_confirm(skb->dev, short_addr, status);
7103+}
7104+
7105+static int mac802154_cmd_disassoc_notify(struct sk_buff *skb)
7106+{
7107+ u8 reason;
7108+
7109+ if (skb->len != 2)
7110+ return -EINVAL;
7111+
7112+ if (skb->pkt_type != PACKET_HOST)
7113+ return 0;
7114+
7115+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
7116+ (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_LONG &&
7117+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_SHORT) ||
7118+ mac_cb(skb)->sa.pan_id != mac_cb(skb)->da.pan_id)
7119+ return -EINVAL;
7120+
7121+ reason = skb->data[1];
7122+
7123+ /* FIXME: checks if this was our coordinator and the disassoc us */
7124+ /* FIXME: if we device, one should receive ->da and not ->sa */
7125+ /* FIXME: the status should also help */
7126+
7127+ return ieee802154_nl_disassoc_indic(skb->dev, &mac_cb(skb)->sa,
7128+ reason);
7129+}
7130+
7131+int mac802154_process_cmd(struct net_device *dev, struct sk_buff *skb)
7132+{
7133+ u8 cmd;
7134+
7135+ if (skb->len < 1) {
7136+ pr_warning("Uncomplete command frame!\n");
7137+ goto drop;
7138+ }
7139+
7140+ cmd = *(skb->data);
7141+ pr_debug("Command %02x on device %s\n", cmd, dev->name);
7142+
7143+ switch (cmd) {
7144+ case IEEE802154_CMD_ASSOCIATION_REQ:
7145+ mac802154_cmd_assoc_req(skb);
7146+ break;
7147+ case IEEE802154_CMD_ASSOCIATION_RESP:
7148+ mac802154_cmd_assoc_resp(skb);
7149+ break;
7150+ case IEEE802154_CMD_DISASSOCIATION_NOTIFY:
7151+ mac802154_cmd_disassoc_notify(skb);
7152+ break;
7153+ case IEEE802154_CMD_BEACON_REQ:
7154+ mac802154_cmd_beacon_req(skb);
7155+ break;
7156+ default:
7157+ pr_debug("Frame type is not supported yet\n");
7158+ goto drop;
7159+ }
7160+
7161+
7162+ kfree_skb(skb);
7163+ return NET_RX_SUCCESS;
7164+
7165+drop:
7166+ kfree_skb(skb);
7167+ return NET_RX_DROP;
7168+}
7169+
7170+static int mac802154_send_cmd(struct net_device *dev,
7171+ struct ieee802154_addr *addr, struct ieee802154_addr *saddr,
7172+ const u8 *buf, int len)
7173+{
7174+ struct sk_buff *skb;
7175+ int err;
7176+
7177+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7178+
7179+ skb = alloc_skb(LL_ALLOCATED_SPACE(dev) + len, GFP_KERNEL);
7180+ if (!skb)
7181+ return -ENOMEM;
7182+
7183+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
7184+
7185+ skb_reset_network_header(skb);
7186+
7187+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_MAC_CMD | MAC_CB_FLAG_ACKREQ;
7188+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
7189+ err = dev_hard_header(skb, dev, ETH_P_IEEE802154, addr, saddr, len);
7190+ if (err < 0) {
7191+ kfree_skb(skb);
7192+ return err;
7193+ }
7194+
7195+ skb_reset_mac_header(skb);
7196+ memcpy(skb_put(skb, len), buf, len);
7197+
7198+ skb->dev = dev;
7199+ skb->protocol = htons(ETH_P_IEEE802154);
7200+
7201+ return dev_queue_xmit(skb);
7202+}
7203+
7204+int mac802154_send_beacon_req(struct net_device *dev)
7205+{
7206+ struct ieee802154_addr addr;
7207+ struct ieee802154_addr saddr;
7208+ u8 cmd = IEEE802154_CMD_BEACON_REQ;
7209+ addr.addr_type = IEEE802154_ADDR_SHORT;
7210+ addr.short_addr = IEEE802154_ADDR_BROADCAST;
7211+ addr.pan_id = IEEE802154_PANID_BROADCAST;
7212+ saddr.addr_type = IEEE802154_ADDR_NONE;
7213+ return mac802154_send_cmd(dev, &addr, &saddr, &cmd, 1);
7214+}
7215+
7216+
7217+static int mac802154_mlme_assoc_req(struct net_device *dev,
7218+ struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
7219+{
7220+ struct ieee802154_addr saddr;
7221+ u8 buf[2];
7222+ int pos = 0;
7223+
7224+ saddr.addr_type = IEEE802154_ADDR_LONG;
7225+ saddr.pan_id = IEEE802154_PANID_BROADCAST;
7226+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
7227+
7228+
7229+ /* FIXME: set PIB/MIB info */
7230+ mac802154_dev_set_pan_id(dev, addr->pan_id);
7231+ mac802154_dev_set_page_channel(dev, page, channel);
7232+ mac802154_dev_set_ieee_addr(dev);
7233+
7234+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_REQ;
7235+ buf[pos++] = cap;
7236+
7237+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
7238+}
7239+
7240+static int mac802154_mlme_assoc_resp(struct net_device *dev,
7241+ struct ieee802154_addr *addr, u16 short_addr, u8 status)
7242+{
7243+ struct ieee802154_addr saddr;
7244+ u8 buf[4];
7245+ int pos = 0;
7246+
7247+ saddr.addr_type = IEEE802154_ADDR_LONG;
7248+ saddr.pan_id = addr->pan_id;
7249+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
7250+
7251+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_RESP;
7252+ buf[pos++] = short_addr;
7253+ buf[pos++] = short_addr >> 8;
7254+ buf[pos++] = status;
7255+
7256+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
7257+}
7258+
7259+static int mac802154_mlme_disassoc_req(struct net_device *dev,
7260+ struct ieee802154_addr *addr, u8 reason)
7261+{
7262+ struct ieee802154_addr saddr;
7263+ u8 buf[2];
7264+ int pos = 0;
7265+ int ret;
7266+
7267+ saddr.addr_type = IEEE802154_ADDR_LONG;
7268+ saddr.pan_id = addr->pan_id;
7269+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
7270+
7271+ buf[pos++] = IEEE802154_CMD_DISASSOCIATION_NOTIFY;
7272+ buf[pos++] = reason;
7273+
7274+ ret = mac802154_send_cmd(dev, addr, &saddr, buf, pos);
7275+
7276+ /* FIXME: this should be after the ack receved */
7277+ mac802154_dev_set_pan_id(dev, 0xffff);
7278+ mac802154_dev_set_short_addr(dev, 0xffff);
7279+ ieee802154_nl_disassoc_confirm(dev, 0x00);
7280+
7281+ return ret;
7282+}
7283+
7284+static int mac802154_mlme_start_req(struct net_device *dev,
7285+ struct ieee802154_addr *addr,
7286+ u8 channel, u8 page,
7287+ u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
7288+ u8 coord_realign)
7289+{
7290+ BUG_ON(addr->addr_type != IEEE802154_ADDR_SHORT);
7291+
7292+ mac802154_dev_set_pan_id(dev, addr->pan_id);
7293+ mac802154_dev_set_short_addr(dev, addr->short_addr);
7294+ mac802154_dev_set_ieee_addr(dev);
7295+ mac802154_dev_set_page_channel(dev, page, channel);
7296+
7297+ /*
7298+ * FIXME: add validation for unused parameters to be sane
7299+ * for SoftMAC
7300+ */
7301+
7302+ if (pan_coord)
7303+ dev->priv_flags |= IFF_IEEE802154_COORD;
7304+ else
7305+ dev->priv_flags &= ~IFF_IEEE802154_COORD;
7306+
7307+ mac802154_dev_set_pan_coord(dev);
7308+ ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
7309+
7310+ return 0;
7311+}
7312+
7313+struct ieee802154_mlme_ops mac802154_mlme_wpan = {
7314+ .assoc_req = mac802154_mlme_assoc_req,
7315+ .assoc_resp = mac802154_mlme_assoc_resp,
7316+ .disassoc_req = mac802154_mlme_disassoc_req,
7317+ .start_req = mac802154_mlme_start_req,
7318+ .scan_req = mac802154_mlme_scan_req,
7319+
7320+ .wpan_ops.get_phy = mac802154_get_phy,
7321+
7322+ .get_pan_id = mac802154_dev_get_pan_id,
7323+ .get_short_addr = mac802154_dev_get_short_addr,
7324+ .get_dsn = mac802154_dev_get_dsn,
7325+ .get_bsn = mac802154_dev_get_bsn,
7326+};
7327+
7328+struct simple_mlme_ops mac802154_mlme_simple = {
7329+ .get_phy = mac802154_get_phy,
7330+};
7331diff --git a/net/mac802154/main.c b/net/mac802154/main.c
7332new file mode 100644
7333index 0000000..b108df0
7334--- /dev/null
7335@@ -0,0 +1,282 @@
7336+/*
7337+ * Copyright (C) 2007, 2008, 2009 Siemens AG
7338+ *
7339+ * This program is free software; you can redistribute it and/or modify
7340+ * it under the terms of the GNU General Public License version 2
7341+ * as published by the Free Software Foundation.
7342+ *
7343+ * This program is distributed in the hope that it will be useful,
7344+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7345+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7346+ * GNU General Public License for more details.
7347+ *
7348+ * You should have received a copy of the GNU General Public License along
7349+ * with this program; if not, write to the Free Software Foundation, Inc.,
7350+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7351+ *
7352+ */
7353+
7354+#include <linux/kernel.h>
7355+#include <linux/netdevice.h>
7356+#include <linux/if_arp.h>
7357+#include <linux/nl802154.h>
7358+#include <net/route.h>
7359+
7360+#include <net/mac802154.h>
7361+#include <net/wpan-phy.h>
7362+
7363+#include "mac802154.h"
7364+#include "mib.h"
7365+
7366+int mac802154_slave_open(struct net_device *dev)
7367+{
7368+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7369+ int res = 0;
7370+
7371+ if (priv->hw->open_count++ == 0) {
7372+ res = priv->hw->ops->start(&priv->hw->hw);
7373+ WARN_ON(res);
7374+ if (res)
7375+ goto err;
7376+ }
7377+
7378+ if (priv->hw->ops->ieee_addr) {
7379+ res = priv->hw->ops->ieee_addr(&priv->hw->hw, dev->dev_addr);
7380+ WARN_ON(res);
7381+ if (res)
7382+ goto err;
7383+ mac802154_dev_set_ieee_addr(dev);
7384+ }
7385+
7386+ netif_start_queue(dev);
7387+ return 0;
7388+err:
7389+ priv->hw->open_count--;
7390+
7391+ return res;
7392+}
7393+
7394+int mac802154_slave_close(struct net_device *dev)
7395+{
7396+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7397+
7398+ dev->priv_flags &= ~IFF_IEEE802154_COORD;
7399+
7400+ netif_stop_queue(dev);
7401+
7402+ if ((--priv->hw->open_count) == 0)
7403+ priv->hw->ops->stop(&priv->hw->hw);
7404+
7405+ return 0;
7406+}
7407+
7408+
7409+static int mac802154_netdev_register(struct wpan_phy *phy,
7410+ struct net_device *dev)
7411+{
7412+ struct mac802154_sub_if_data *priv;
7413+ struct mac802154_priv *ipriv;
7414+ int err;
7415+
7416+ ipriv = wpan_phy_priv(phy);
7417+
7418+ priv = netdev_priv(dev);
7419+ priv->dev = dev;
7420+ priv->hw = ipriv;
7421+
7422+ dev->needed_headroom = ipriv->hw.extra_tx_headroom;
7423+
7424+ SET_NETDEV_DEV(dev, &ipriv->phy->dev);
7425+
7426+ mutex_lock(&ipriv->slaves_mtx);
7427+ if (!ipriv->running) {
7428+ mutex_unlock(&ipriv->slaves_mtx);
7429+ return -ENODEV;
7430+ }
7431+ mutex_unlock(&ipriv->slaves_mtx);
7432+
7433+ err = register_netdev(dev);
7434+ if (err < 0)
7435+ return err;
7436+
7437+ rtnl_lock();
7438+ mutex_lock(&ipriv->slaves_mtx);
7439+ list_add_tail_rcu(&priv->list, &ipriv->slaves);
7440+ mutex_unlock(&ipriv->slaves_mtx);
7441+ rtnl_unlock();
7442+
7443+ return 0;
7444+}
7445+
7446+static void mac802154_del_iface(struct wpan_phy *phy,
7447+ struct net_device *dev)
7448+{
7449+ struct mac802154_sub_if_data *sdata;
7450+ ASSERT_RTNL();
7451+
7452+ sdata = netdev_priv(dev);
7453+
7454+ BUG_ON(sdata->hw->phy != phy);
7455+
7456+ mutex_lock(&sdata->hw->slaves_mtx);
7457+ list_del_rcu(&sdata->list);
7458+ mutex_unlock(&sdata->hw->slaves_mtx);
7459+
7460+ synchronize_rcu();
7461+ unregister_netdevice(sdata->dev);
7462+}
7463+
7464+static struct net_device *mac802154_add_iface(struct wpan_phy *phy,
7465+ const char *name, int type)
7466+{
7467+ struct net_device *dev;
7468+ int err = -ENOMEM;
7469+
7470+ switch (type) {
7471+ case IEEE802154_DEV_WPAN:
7472+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
7473+ name, mac802154_wpan_setup);
7474+ break;
7475+ case IEEE802154_DEV_MONITOR:
7476+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
7477+ name, mac802154_monitor_setup);
7478+ break;
7479+ case IEEE802154_DEV_SMAC:
7480+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
7481+ name, mac802154_smac_setup);
7482+ break;
7483+ default:
7484+ dev = NULL;
7485+ err = -EINVAL;
7486+ break;
7487+ }
7488+ if (!dev)
7489+ goto err;
7490+
7491+
7492+ err = mac802154_netdev_register(phy, dev);
7493+
7494+ if (err)
7495+ goto err_free;
7496+
7497+ dev_hold(dev); /* we return a device w/ incremented refcount */
7498+ return dev;
7499+
7500+err_free:
7501+ free_netdev(dev);
7502+err:
7503+ return ERR_PTR(err);
7504+}
7505+
7506+
7507+struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
7508+ struct ieee802154_ops *ops)
7509+{
7510+ struct wpan_phy *phy;
7511+ struct mac802154_priv *priv;
7512+
7513+ phy = wpan_phy_alloc(ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_size);
7514+ if (!phy) {
7515+ printk(KERN_ERR
7516+ "Failure to initialize master IEEE802154 device\n");
7517+ return NULL;
7518+ }
7519+
7520+ priv = wpan_phy_priv(phy);
7521+ priv->hw.phy = priv->phy = phy;
7522+
7523+ priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
7524+
7525+ BUG_ON(!ops);
7526+ BUG_ON(!ops->xmit);
7527+ BUG_ON(!ops->ed);
7528+ BUG_ON(!ops->start);
7529+ BUG_ON(!ops->stop);
7530+
7531+ priv->ops = ops;
7532+
7533+ INIT_LIST_HEAD(&priv->slaves);
7534+ mutex_init(&priv->slaves_mtx);
7535+
7536+ return &priv->hw;
7537+}
7538+EXPORT_SYMBOL(ieee802154_alloc_device);
7539+
7540+void ieee802154_free_device(struct ieee802154_dev *hw)
7541+{
7542+ struct mac802154_priv *priv = mac802154_to_priv(hw);
7543+
7544+ BUG_ON(!list_empty(&priv->slaves));
7545+
7546+ wpan_phy_free(priv->phy);
7547+}
7548+EXPORT_SYMBOL(ieee802154_free_device);
7549+
7550+int ieee802154_register_device(struct ieee802154_dev *dev)
7551+{
7552+ struct mac802154_priv *priv = mac802154_to_priv(dev);
7553+ int rc;
7554+
7555+ priv->dev_workqueue =
7556+ create_singlethread_workqueue(wpan_phy_name(priv->phy));
7557+ if (!priv->dev_workqueue) {
7558+ rc = -ENOMEM;
7559+ goto out;
7560+ }
7561+
7562+ wpan_phy_set_dev(priv->phy, priv->hw.parent);
7563+
7564+ priv->phy->add_iface = mac802154_add_iface;
7565+ priv->phy->del_iface = mac802154_del_iface;
7566+
7567+ rc = wpan_phy_register(priv->phy);
7568+ if (rc < 0)
7569+ goto out_wq;
7570+
7571+ rtnl_lock();
7572+ mutex_lock(&priv->slaves_mtx);
7573+ priv->running = 1;
7574+ mutex_unlock(&priv->slaves_mtx);
7575+ rtnl_unlock();
7576+
7577+ return 0;
7578+
7579+out_wq:
7580+ destroy_workqueue(priv->dev_workqueue);
7581+out:
7582+ return rc;
7583+}
7584+EXPORT_SYMBOL(ieee802154_register_device);
7585+
7586+void ieee802154_unregister_device(struct ieee802154_dev *dev)
7587+{
7588+ struct mac802154_priv *priv = mac802154_to_priv(dev);
7589+ struct mac802154_sub_if_data *sdata, *next;
7590+
7591+
7592+ flush_workqueue(priv->dev_workqueue);
7593+ destroy_workqueue(priv->dev_workqueue);
7594+
7595+ rtnl_lock();
7596+
7597+ mutex_lock(&priv->slaves_mtx);
7598+ priv->running = 0;
7599+ mutex_unlock(&priv->slaves_mtx);
7600+
7601+ list_for_each_entry_safe(sdata, next, &priv->slaves, list) {
7602+ mutex_lock(&sdata->hw->slaves_mtx);
7603+ list_del(&sdata->list);
7604+ mutex_unlock(&sdata->hw->slaves_mtx);
7605+
7606+ unregister_netdevice(sdata->dev);
7607+ }
7608+
7609+ rtnl_unlock();
7610+
7611+ wpan_phy_unregister(priv->phy);
7612+}
7613+EXPORT_SYMBOL(ieee802154_unregister_device);
7614+
7615+MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
7616+MODULE_LICENSE("GPL v2");
7617+
7618diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
7619new file mode 100644
7620index 0000000..23871df
7621--- /dev/null
7622@@ -0,0 +1,249 @@
7623+/*
7624+ * Copyright 2007, 2008, 2009 Siemens AG
7625+ *
7626+ * This program is free software; you can redistribute it and/or modify
7627+ * it under the terms of the GNU General Public License version 2
7628+ * as published by the Free Software Foundation.
7629+ *
7630+ * This program is distributed in the hope that it will be useful,
7631+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7632+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7633+ * GNU General Public License for more details.
7634+ *
7635+ * You should have received a copy of the GNU General Public License along
7636+ * with this program; if not, write to the Free Software Foundation, Inc.,
7637+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7638+ *
7639+ * Written by:
7640+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7641+ * Sergey Lapin <slapin@ossfans.org>
7642+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7643+ */
7644+
7645+#include <linux/if_arp.h>
7646+
7647+#include <net/mac802154.h>
7648+#include <net/wpan-phy.h>
7649+
7650+#include "mac802154.h"
7651+#include "mib.h"
7652+
7653+struct phy_chan_notify_work {
7654+ struct work_struct work;
7655+ struct net_device *dev;
7656+};
7657+
7658+struct hw_addr_filt_notify_work {
7659+ struct work_struct work;
7660+ struct net_device *dev;
7661+ unsigned long changed;
7662+};
7663+
7664+static void hw_addr_notify(struct work_struct *work)
7665+{
7666+ struct hw_addr_filt_notify_work *nw = container_of(work,
7667+ struct hw_addr_filt_notify_work, work);
7668+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
7669+ int res;
7670+
7671+ res = hw->ops->set_hw_addr_filt(&hw->hw,
7672+ &hw->hw.hw_filt, nw->changed);
7673+ if (res)
7674+ pr_debug("%s: failed changed mask %lx\n",
7675+ __func__, nw->changed);
7676+
7677+ kfree(nw);
7678+
7679+ return;
7680+}
7681+
7682+static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
7683+{
7684+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7685+ struct hw_addr_filt_notify_work *work;
7686+
7687+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
7688+ if (!work)
7689+ return;
7690+
7691+ INIT_WORK(&work->work, hw_addr_notify);
7692+ work->dev = dev;
7693+ work->changed = changed;
7694+ queue_work(priv->hw->dev_workqueue, &work->work);
7695+
7696+ return;
7697+}
7698+
7699+static void phy_chan_notify(struct work_struct *work)
7700+{
7701+ struct phy_chan_notify_work *nw = container_of(work,
7702+ struct phy_chan_notify_work, work);
7703+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
7704+ struct mac802154_sub_if_data *priv = netdev_priv(nw->dev);
7705+ int res;
7706+
7707+ res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan);
7708+ if (res)
7709+ pr_debug("set_channel failed\n");
7710+
7711+ kfree(nw);
7712+
7713+ return;
7714+}
7715+
7716+u16 mac802154_dev_get_pan_id(const struct net_device *dev)
7717+{
7718+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7719+ u16 ret;
7720+
7721+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7722+
7723+ spin_lock_bh(&priv->mib_lock);
7724+ ret = priv->pan_id;
7725+ spin_unlock_bh(&priv->mib_lock);
7726+
7727+ return ret;
7728+}
7729+
7730+u16 mac802154_dev_get_short_addr(const struct net_device *dev)
7731+{
7732+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7733+ u16 ret;
7734+
7735+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7736+
7737+ spin_lock_bh(&priv->mib_lock);
7738+ ret = priv->short_addr;
7739+ spin_unlock_bh(&priv->mib_lock);
7740+
7741+ return ret;
7742+}
7743+
7744+void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
7745+{
7746+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7747+
7748+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7749+
7750+ spin_lock_bh(&priv->mib_lock);
7751+ priv->pan_id = val;
7752+ spin_unlock_bh(&priv->mib_lock);
7753+
7754+ if (priv->hw->ops->set_hw_addr_filt &&
7755+ (priv->hw->hw.hw_filt.pan_id != priv->pan_id)) {
7756+ priv->hw->hw.hw_filt.pan_id = priv->pan_id;
7757+ set_hw_addr_filt(dev, IEEE802515_PANID_CHANGED);
7758+ }
7759+}
7760+
7761+void mac802154_dev_set_pan_coord(struct net_device *dev)
7762+{
7763+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7764+ int pan_coord = !!(dev->priv_flags & IFF_IEEE802154_COORD);
7765+
7766+ if (priv->hw->ops->set_hw_addr_filt &&
7767+ (priv->hw->hw.hw_filt.pan_coord != pan_coord)) {
7768+ priv->hw->hw.hw_filt.pan_coord = pan_coord;
7769+ set_hw_addr_filt(dev, IEEE802515_PANC_CHANGED);
7770+ }
7771+}
7772+
7773+void mac802154_dev_set_short_addr(struct net_device *dev, u16 val)
7774+{
7775+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7776+
7777+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7778+
7779+ spin_lock_bh(&priv->mib_lock);
7780+ priv->short_addr = val;
7781+ spin_unlock_bh(&priv->mib_lock);
7782+
7783+ if (priv->hw->ops->set_hw_addr_filt &&
7784+ (priv->hw->hw.hw_filt.short_addr != priv->short_addr)) {
7785+ priv->hw->hw.hw_filt.short_addr = priv->short_addr;
7786+ set_hw_addr_filt(dev, IEEE802515_SADDR_CHANGED);
7787+ }
7788+}
7789+
7790+void mac802154_dev_set_ieee_addr(struct net_device *dev)
7791+{
7792+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7793+
7794+ if (priv->hw->ops->set_hw_addr_filt &&
7795+ memcmp(priv->hw->hw.hw_filt.ieee_addr,
7796+ dev->dev_addr, IEEE802154_ALEN)) {
7797+ memcpy(priv->hw->hw.hw_filt.ieee_addr,
7798+ dev->dev_addr, IEEE802154_ALEN);
7799+ set_hw_addr_filt(dev, IEEE802515_IEEEADDR_CHANGED);
7800+ }
7801+}
7802+
7803+void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
7804+{
7805+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7806+ struct phy_chan_notify_work *work;
7807+
7808+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7809+
7810+ spin_lock_bh(&priv->mib_lock);
7811+ priv->page = page;
7812+ priv->chan = chan;
7813+ spin_unlock_bh(&priv->mib_lock);
7814+
7815+ if (priv->hw->phy->current_channel != priv->chan ||
7816+ priv->hw->phy->current_page != priv->page) {
7817+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
7818+ if (!work)
7819+ return;
7820+
7821+ INIT_WORK(&work->work, phy_chan_notify);
7822+ work->dev = dev;
7823+ queue_work(priv->hw->dev_workqueue, &work->work);
7824+ }
7825+}
7826+
7827+u8 mac802154_dev_get_dsn(const struct net_device *dev)
7828+{
7829+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7830+ u16 ret;
7831+
7832+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7833+
7834+ spin_lock_bh(&priv->mib_lock);
7835+ ret = priv->dsn++;
7836+ spin_unlock_bh(&priv->mib_lock);
7837+
7838+ return ret;
7839+}
7840+
7841+u8 mac802154_dev_get_bsn(const struct net_device *dev)
7842+{
7843+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7844+ u16 ret;
7845+
7846+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7847+
7848+ spin_lock_bh(&priv->mib_lock);
7849+ ret = priv->bsn++;
7850+ spin_unlock_bh(&priv->mib_lock);
7851+
7852+ return ret;
7853+}
7854+
7855+struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev)
7856+{
7857+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7858+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7859+
7860+ return priv->hw;
7861+}
7862+
7863+struct wpan_phy *mac802154_get_phy(const struct net_device *dev)
7864+{
7865+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7866+ BUG_ON(dev->type != ARPHRD_IEEE802154
7867+ && dev->type != ARPHRD_IEEE802154_MONITOR
7868+ && dev->type != ARPHRD_SMAC);
7869+
7870+ return to_phy(get_device(&priv->hw->phy->dev));
7871+}
7872diff --git a/net/mac802154/mib.h b/net/mac802154/mib.h
7873new file mode 100644
7874index 0000000..228f6d0
7875--- /dev/null
7876@@ -0,0 +1,35 @@
7877+/*
7878+ * Copyright 2008 Siemens AG
7879+ *
7880+ * This program is free software; you can redistribute it and/or modify
7881+ * it under the terms of the GNU General Public License version 2
7882+ * as published by the Free Software Foundation.
7883+ *
7884+ * This program is distributed in the hope that it will be useful,
7885+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7886+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7887+ * GNU General Public License for more details.
7888+ *
7889+ * You should have received a copy of the GNU General Public License along
7890+ * with this program; if not, write to the Free Software Foundation, Inc.,
7891+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7892+ *
7893+ */
7894+
7895+#ifndef MIB802154_H
7896+#define MIB802154_H
7897+
7898+/* FIXME: should be dropped in favour of generic MIB API */
7899+u8 mac802154_dev_get_dsn(const struct net_device *dev);
7900+u8 mac802154_dev_get_bsn(const struct net_device *dev);
7901+u16 mac802154_dev_get_pan_id(const struct net_device *dev);
7902+u16 mac802154_dev_get_short_addr(const struct net_device *dev);
7903+void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
7904+void mac802154_dev_set_pan_coord(struct net_device *dev);
7905+void mac802154_dev_set_short_addr(struct net_device *dev, u16 val);
7906+void mac802154_dev_set_ieee_addr(struct net_device *dev);
7907+void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
7908+struct wpan_phy *mac802154_get_phy(const struct net_device *dev);
7909+
7910+
7911+#endif
7912diff --git a/net/mac802154/monitor.c b/net/mac802154/monitor.c
7913new file mode 100644
7914index 0000000..3a24599
7915--- /dev/null
7916@@ -0,0 +1,116 @@
7917+/*
7918+ * Copyright 2007, 2008, 2009 Siemens AG
7919+ *
7920+ * This program is free software; you can redistribute it and/or modify
7921+ * it under the terms of the GNU General Public License version 2
7922+ * as published by the Free Software Foundation.
7923+ *
7924+ * This program is distributed in the hope that it will be useful,
7925+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7926+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7927+ * GNU General Public License for more details.
7928+ *
7929+ * You should have received a copy of the GNU General Public License along
7930+ * with this program; if not, write to the Free Software Foundation, Inc.,
7931+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7932+ *
7933+ * Written by:
7934+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7935+ * Sergey Lapin <slapin@ossfans.org>
7936+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7937+ */
7938+
7939+#include <linux/netdevice.h>
7940+#include <linux/skbuff.h>
7941+#include <linux/if_arp.h>
7942+#include <linux/nl802154.h>
7943+#include <linux/crc-ccitt.h>
7944+
7945+#include <net/mac802154.h>
7946+#include <net/wpan-phy.h>
7947+
7948+#include "mac802154.h"
7949+
7950+static netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev)
7951+{
7952+ struct mac802154_sub_if_data *priv;
7953+ u8 chan, page;
7954+
7955+ priv = netdev_priv(dev);
7956+
7957+ /* FIXME: locking */
7958+ chan = priv->hw->phy->current_channel;
7959+ page = priv->hw->phy->current_page;
7960+
7961+ if (chan == (u8)-1) /* not init */
7962+ return NETDEV_TX_OK;
7963+
7964+ BUG_ON(page >= WPAN_NUM_PAGES);
7965+ BUG_ON(chan >= 27);
7966+
7967+ skb->skb_iif = dev->ifindex;
7968+ dev->stats.tx_packets++;
7969+ dev->stats.tx_bytes += skb->len;
7970+
7971+ return mac802154_tx(priv->hw, skb, page, chan);
7972+}
7973+
7974+
7975+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb)
7976+{
7977+ struct sk_buff *skb2;
7978+ struct mac802154_sub_if_data *sdata;
7979+ u16 crc = crc_ccitt(0, skb->data, skb->len);
7980+ u8 *data;
7981+
7982+ rcu_read_lock();
7983+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
7984+ if (sdata->type != IEEE802154_DEV_MONITOR)
7985+ continue;
7986+
7987+ skb2 = skb_clone(skb, GFP_ATOMIC);
7988+ skb2->dev = sdata->dev;
7989+ skb2->pkt_type = PACKET_HOST;
7990+ data = skb_put(skb2, 2);
7991+ data[0] = crc & 0xff;
7992+ data[1] = crc >> 8;
7993+
7994+ if (in_interrupt())
7995+ netif_rx(skb2);
7996+ else
7997+ netif_rx_ni(skb2);
7998+ }
7999+ rcu_read_unlock();
8000+}
8001+
8002+static const struct net_device_ops mac802154_monitor_ops = {
8003+ .ndo_open = mac802154_slave_open,
8004+ .ndo_stop = mac802154_slave_close,
8005+ .ndo_start_xmit = mac802154_monitor_xmit,
8006+};
8007+
8008+void mac802154_monitor_setup(struct net_device *dev)
8009+{
8010+ struct mac802154_sub_if_data *priv;
8011+
8012+ dev->addr_len = 0;
8013+ dev->features = NETIF_F_NO_CSUM;
8014+ dev->hard_header_len = 0;
8015+ dev->needed_tailroom = 2; /* FCS */
8016+ dev->mtu = 127;
8017+ dev->tx_queue_len = 10;
8018+ dev->type = ARPHRD_IEEE802154_MONITOR;
8019+ dev->flags = IFF_NOARP | IFF_BROADCAST;
8020+ dev->watchdog_timeo = 0;
8021+
8022+ dev->destructor = free_netdev;
8023+ dev->netdev_ops = &mac802154_monitor_ops;
8024+ dev->ml_priv = &mac802154_mlme_simple;
8025+
8026+ priv = netdev_priv(dev);
8027+ priv->type = IEEE802154_DEV_MONITOR;
8028+
8029+ priv->chan = -1; /* not initialized */
8030+ priv->page = 0; /* for compat */
8031+}
8032+
8033diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
8034new file mode 100644
8035index 0000000..0e9d5d4
8036--- /dev/null
8037@@ -0,0 +1,117 @@
8038+/*
8039+ * Copyright (C) 2007, 2008, 2009 Siemens AG
8040+ *
8041+ * This program is free software; you can redistribute it and/or modify
8042+ * it under the terms of the GNU General Public License version 2
8043+ * as published by the Free Software Foundation.
8044+ *
8045+ * This program is distributed in the hope that it will be useful,
8046+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8047+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8048+ * GNU General Public License for more details.
8049+ *
8050+ * You should have received a copy of the GNU General Public License along
8051+ * with this program; if not, write to the Free Software Foundation, Inc.,
8052+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8053+ *
8054+ * Written by:
8055+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
8056+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8057+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8058+ */
8059+
8060+#include <linux/kernel.h>
8061+#include <linux/module.h>
8062+#include <linux/workqueue.h>
8063+#include <linux/netdevice.h>
8064+#include <linux/crc-ccitt.h>
8065+
8066+#include <net/mac802154.h>
8067+#include <net/ieee802154_netdev.h>
8068+
8069+#include "mac802154.h"
8070+
8071+static void mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb)
8072+{
8073+ struct mac802154_priv *priv = mac802154_to_priv(hw);
8074+
8075+ BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb));
8076+ pr_debug("%s()\n", __func__);
8077+
8078+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
8079+ u16 crc;
8080+
8081+ if (skb->len < 2) {
8082+ pr_debug("%s(): Got invalid frame\n", __func__);
8083+ goto out;
8084+ }
8085+ crc = crc_ccitt(0, skb->data, skb->len);
8086+ if (crc) {
8087+ pr_debug("%s(): CRC mismatch\n", __func__);
8088+ goto out;
8089+ }
8090+ skb_trim(skb, skb->len - 2); /* CRC */
8091+ }
8092+
8093+ mac802154_monitors_rx(priv, skb);
8094+ mac802154_smacs_rx(priv, skb);
8095+ mac802154_wpans_rx(priv, skb);
8096+
8097+out:
8098+ dev_kfree_skb(skb);
8099+ return;
8100+}
8101+
8102+static void __mac802154_rx_prepare(struct ieee802154_dev *dev,
8103+ struct sk_buff *skb, u8 lqi)
8104+{
8105+ BUG_ON(!skb);
8106+
8107+ mac_cb(skb)->lqi = lqi;
8108+
8109+ skb->protocol = htons(ETH_P_IEEE802154);
8110+
8111+ skb_reset_mac_header(skb);
8112+}
8113+
8114+void mac802154_rx(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi)
8115+{
8116+ __mac802154_rx_prepare(dev, skb, lqi);
8117+
8118+ mac802154_subif_rx(dev, skb);
8119+}
8120+EXPORT_SYMBOL(mac802154_rx);
8121+
8122+struct rx_work {
8123+ struct sk_buff *skb;
8124+ struct work_struct work;
8125+ struct ieee802154_dev *dev;
8126+};
8127+
8128+static void mac802154_rx_worker(struct work_struct *work)
8129+{
8130+ struct rx_work *rw = container_of(work, struct rx_work, work);
8131+ struct sk_buff *skb = rw->skb;
8132+
8133+ mac802154_subif_rx(rw->dev, skb);
8134+ kfree(rw);
8135+}
8136+
8137+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev,
8138+ struct sk_buff *skb, u8 lqi)
8139+{
8140+ struct mac802154_priv *priv = mac802154_to_priv(dev);
8141+ struct rx_work *work = kzalloc(sizeof(struct rx_work), GFP_ATOMIC);
8142+
8143+ if (!work)
8144+ return;
8145+
8146+ __mac802154_rx_prepare(dev, skb, lqi);
8147+
8148+ INIT_WORK(&work->work, mac802154_rx_worker);
8149+ work->skb = skb;
8150+ work->dev = dev;
8151+
8152+ queue_work(priv->dev_workqueue, &work->work);
8153+}
8154+EXPORT_SYMBOL(ieee802154_rx_irqsafe);
8155diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
8156new file mode 100644
8157index 0000000..7c6f313
8158--- /dev/null
8159@@ -0,0 +1,203 @@
8160+/*
8161+ * scan.c
8162+ *
8163+ * Description: MAC scan helper functions.
8164+ *
8165+ * Copyright (C) 2007, 2008 Siemens AG
8166+ *
8167+ * This program is free software; you can redistribute it and/or modify
8168+ * it under the terms of the GNU General Public License version 2
8169+ * as published by the Free Software Foundation.
8170+ *
8171+ * This program is distributed in the hope that it will be useful,
8172+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8173+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8174+ * GNU General Public License for more details.
8175+ *
8176+ * You should have received a copy of the GNU General Public License along
8177+ * with this program; if not, write to the Free Software Foundation, Inc.,
8178+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8179+ *
8180+ * Written by:
8181+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
8182+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8183+ */
8184+#include <linux/net.h>
8185+#include <linux/module.h>
8186+#include <linux/sched.h>
8187+#include <linux/netdevice.h>
8188+
8189+#include <net/mac802154.h>
8190+#include <net/nl802154.h>
8191+#include <net/ieee802154.h>
8192+#include <net/ieee802154_netdev.h>
8193+#include <net/wpan-phy.h>
8194+
8195+#include "mac802154.h"
8196+
8197+/*
8198+ * ED scan is periodic issuing of ed device function
8199+ * on evry permitted channel, so it is virtually PHY-only scan */
8200+
8201+struct scan_work {
8202+ struct work_struct work;
8203+
8204+ int (*scan_ch)(struct scan_work *work, int channel, u8 duration);
8205+ struct net_device *dev;
8206+
8207+ u8 edl[27];
8208+
8209+ u8 type;
8210+ u32 channels;
8211+ u8 page;
8212+ u8 duration;
8213+};
8214+
8215+static int scan_ed(struct scan_work *work, int channel, u8 duration)
8216+{
8217+ int ret;
8218+ struct mac802154_priv *hw = mac802154_slave_get_priv(work->dev);
8219+ pr_debug("ed scan channel %d duration %d\n", channel, duration);
8220+ mutex_lock(&hw->phy->pib_lock);
8221+ ret = hw->ops->ed(&hw->hw, &work->edl[channel]);
8222+ mutex_unlock(&hw->phy->pib_lock);
8223+ pr_debug("ed scan channel %d value %d\n", channel, work->edl[channel]);
8224+ return ret;
8225+}
8226+
8227+static int scan_passive(struct scan_work *work, int channel, u8 duration)
8228+{
8229+ unsigned long j;
8230+ pr_debug("passive scan channel %d duration %d\n", channel, duration);
8231+
8232+ /* Hope 2 msecs will be enough for scan */
8233+ j = msecs_to_jiffies(2);
8234+ while (j > 0)
8235+ j = schedule_timeout(j);
8236+
8237+ return 0;
8238+}
8239+
8240+/* Active scan is periodic submission of beacon request
8241+ * and waiting for beacons which is useful for collecting LWPAN information */
8242+static int scan_active(struct scan_work *work, int channel, u8 duration)
8243+{
8244+ int ret;
8245+ pr_debug("active scan channel %d duration %d\n", channel, duration);
8246+ ret = mac802154_send_beacon_req(work->dev);
8247+ if (ret)
8248+ return ret;
8249+ return scan_passive(work, channel, duration);
8250+}
8251+
8252+static int scan_orphan(struct scan_work *work, int channel, u8 duration)
8253+{
8254+ pr_debug("orphan scan channel %d duration %d\n", channel, duration);
8255+ return 0;
8256+}
8257+
8258+static void scanner(struct work_struct *work)
8259+{
8260+ struct scan_work *sw = container_of(work, struct scan_work, work);
8261+ struct mac802154_priv *hw = mac802154_slave_get_priv(sw->dev);
8262+ struct mac802154_sub_if_data *priv = netdev_priv(sw->dev);
8263+ int i;
8264+ int ret;
8265+
8266+ for (i = 0; i < 27; i++) {
8267+ if (!(sw->channels & (1 << i)))
8268+ continue;
8269+
8270+ mutex_lock(&hw->phy->pib_lock);
8271+ ret = hw->ops->set_channel(&hw->hw, sw->page, i);
8272+ mutex_unlock(&hw->phy->pib_lock);
8273+ if (ret)
8274+ goto exit_error;
8275+
8276+ priv->chan = i;
8277+ priv->page = sw->page;
8278+
8279+ ret = sw->scan_ch(sw, i, sw->duration);
8280+ if (ret)
8281+ goto exit_error;
8282+
8283+ sw->channels &= ~(1 << i);
8284+ }
8285+
8286+ ieee802154_nl_scan_confirm(sw->dev, IEEE802154_SUCCESS, sw->type,
8287+ sw->channels, sw->page, sw->edl/*, NULL */);
8288+
8289+ kfree(sw);
8290+
8291+ return;
8292+
8293+exit_error:
8294+ ieee802154_nl_scan_confirm(sw->dev, IEEE802154_INVALID_PARAMETER,
8295+ sw->type, sw->channels, sw->page, NULL/*, NULL */);
8296+ kfree(sw);
8297+ return;
8298+}
8299+
8300+/*
8301+ * Alloc ed_detect list for ED scan.
8302+ *
8303+ * @param mac current mac pointer
8304+ * @param type type of the scan to be performed
8305+ * @param channels 32-bit mask of requested to scan channels
8306+ * @param duration scan duration, see ieee802.15.4-2003.pdf, page 145.
8307+ * @return 0 if request is ok, errno otherwise.
8308+ */
8309+int mac802154_mlme_scan_req(struct net_device *dev,
8310+ u8 type, u32 channels, u8 page, u8 duration)
8311+{
8312+ struct mac802154_priv *hw = mac802154_slave_get_priv(dev);
8313+ struct scan_work *work;
8314+
8315+ pr_debug("%s()\n", __func__);
8316+
8317+ if (page > WPAN_NUM_PAGES)
8318+ goto inval;
8319+ if (duration > 14)
8320+ goto inval;
8321+ if (channels & ~hw->phy->channels_supported[page])
8322+ goto inval;
8323+
8324+ work = kzalloc(sizeof(struct scan_work), GFP_KERNEL);
8325+ if (!work)
8326+ goto inval;
8327+
8328+ work->dev = dev;
8329+ work->channels = channels;
8330+ work->page = page;
8331+ work->duration = duration;
8332+ work->type = type;
8333+
8334+ switch (type) {
8335+ case IEEE802154_MAC_SCAN_ED:
8336+ work->scan_ch = scan_ed;
8337+ break;
8338+ case IEEE802154_MAC_SCAN_ACTIVE:
8339+ work->scan_ch = scan_active;
8340+ break;
8341+ case IEEE802154_MAC_SCAN_PASSIVE:
8342+ work->scan_ch = scan_passive;
8343+ break;
8344+ case IEEE802154_MAC_SCAN_ORPHAN:
8345+ work->scan_ch = scan_orphan;
8346+ break;
8347+ default:
8348+ pr_debug("%s(): invalid type %d\n", __func__, type);
8349+ goto inval;
8350+ }
8351+
8352+ INIT_WORK(&work->work, scanner);
8353+ queue_work(hw->dev_workqueue, &work->work);
8354+
8355+ return 0;
8356+
8357+inval:
8358+ ieee802154_nl_scan_confirm(dev, IEEE802154_INVALID_PARAMETER, type,
8359+ channels, page, NULL/*, NULL */);
8360+ return -EINVAL;
8361+}
8362+
8363diff --git a/net/mac802154/smac.c b/net/mac802154/smac.c
8364new file mode 100644
8365index 0000000..b11f0ec
8366--- /dev/null
8367@@ -0,0 +1,127 @@
8368+/*
8369+ * Copyright 2010 Siemens AG
8370+ *
8371+ * This program is free software; you can redistribute it and/or modify
8372+ * it under the terms of the GNU General Public License version 2
8373+ * as published by the Free Software Foundation.
8374+ *
8375+ * This program is distributed in the hope that it will be useful,
8376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8378+ * GNU General Public License for more details.
8379+ *
8380+ * You should have received a copy of the GNU General Public License along
8381+ * with this program; if not, write to the Free Software Foundation, Inc.,
8382+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8383+ *
8384+ * Written by:
8385+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8386+ */
8387+
8388+#include <linux/netdevice.h>
8389+#include <linux/skbuff.h>
8390+#include <linux/if_arp.h>
8391+#include <linux/nl802154.h>
8392+
8393+#include <net/mac802154.h>
8394+#include <net/wpan-phy.h>
8395+
8396+#include "mac802154.h"
8397+
8398+static const u8 smac_header[] = {0x7E, 0xFF};
8399+
8400+static netdev_tx_t mac802154_smac_xmit(struct sk_buff *skb, struct net_device *dev)
8401+{
8402+ struct mac802154_sub_if_data *priv;
8403+ u8 chan, page;
8404+
8405+ priv = netdev_priv(dev);
8406+
8407+ /* FIXME: locking */
8408+ chan = priv->hw->phy->current_channel;
8409+ page = priv->hw->phy->current_page;
8410+
8411+ if (chan == (u8)-1) /* not init */
8412+ return NETDEV_TX_OK;
8413+
8414+ BUG_ON(page >= WPAN_NUM_PAGES);
8415+ BUG_ON(chan >= 27);
8416+
8417+ memcpy(skb_push(skb, sizeof(smac_header)), smac_header, sizeof(smac_header));
8418+
8419+ skb->skb_iif = dev->ifindex;
8420+ dev->stats.tx_packets++;
8421+ dev->stats.tx_bytes += skb->len;
8422+
8423+ return mac802154_tx(priv->hw, skb, page, chan);
8424+}
8425+
8426+void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb)
8427+{
8428+ struct mac802154_sub_if_data *sdata;
8429+
8430+ if (skb->len < sizeof(smac_header))
8431+ return;
8432+
8433+ if (memcmp(skb->data, smac_header, sizeof(smac_header)))
8434+ return;
8435+
8436+ /*
8437+ * Currently we are the owner of the skb.
8438+ * We can change it's data pointers, provided we change them
8439+ * back at the end.
8440+ */
8441+
8442+ skb_pull(skb, sizeof(smac_header));
8443+
8444+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
8445+ struct sk_buff *skb2;
8446+
8447+ if (sdata->type != IEEE802154_DEV_SMAC)
8448+ continue;
8449+
8450+ skb2 = skb_clone(skb, GFP_ATOMIC);
8451+ skb2->dev = sdata->dev;
8452+ skb2->pkt_type = PACKET_HOST;
8453+
8454+ if (in_interrupt())
8455+ netif_rx(skb2);
8456+ else
8457+ netif_rx_ni(skb2);
8458+ }
8459+ rcu_read_unlock();
8460+
8461+ skb_push(skb, sizeof(smac_header));
8462+}
8463+
8464+static const struct net_device_ops mac802154_smac_ops = {
8465+ .ndo_open = mac802154_slave_open,
8466+ .ndo_stop = mac802154_slave_close,
8467+ .ndo_start_xmit = mac802154_smac_xmit,
8468+};
8469+
8470+void mac802154_smac_setup(struct net_device *dev)
8471+{
8472+ struct mac802154_sub_if_data *priv;
8473+
8474+ dev->addr_len = 0;
8475+ dev->features = NETIF_F_NO_CSUM;
8476+ dev->hard_header_len = 2;
8477+ dev->needed_tailroom = 2; /* FCS */
8478+ dev->mtu = 123; /* 127 - 2 (FCS) - 2 (header) */
8479+ dev->tx_queue_len = 10;
8480+ dev->type = ARPHRD_SMAC;
8481+ dev->flags = IFF_NOARP | IFF_BROADCAST;
8482+ dev->watchdog_timeo = 0;
8483+
8484+ dev->destructor = free_netdev;
8485+ dev->netdev_ops = &mac802154_smac_ops;
8486+ dev->ml_priv = &mac802154_mlme_simple;
8487+
8488+ priv = netdev_priv(dev);
8489+ priv->type = IEEE802154_DEV_SMAC;
8490+
8491+ priv->chan = -1; /* not initialized */
8492+ priv->page = 0; /* for compat */
8493+}
8494+
8495diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
8496new file mode 100644
8497index 0000000..0703195
8498--- /dev/null
8499@@ -0,0 +1,106 @@
8500+/*
8501+ * Copyright 2007, 2008, 2009 Siemens AG
8502+ *
8503+ * This program is free software; you can redistribute it and/or modify
8504+ * it under the terms of the GNU General Public License version 2
8505+ * as published by the Free Software Foundation.
8506+ *
8507+ * This program is distributed in the hope that it will be useful,
8508+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8509+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8510+ * GNU General Public License for more details.
8511+ *
8512+ * You should have received a copy of the GNU General Public License along
8513+ * with this program; if not, write to the Free Software Foundation, Inc.,
8514+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8515+ *
8516+ * Written by:
8517+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8518+ * Sergey Lapin <slapin@ossfans.org>
8519+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8520+ */
8521+
8522+#include <linux/netdevice.h>
8523+#include <linux/if_arp.h>
8524+#include <linux/crc-ccitt.h>
8525+
8526+#include <net/mac802154.h>
8527+#include <net/wpan-phy.h>
8528+
8529+#include "mac802154.h"
8530+
8531+struct xmit_work {
8532+ struct sk_buff *skb;
8533+ struct work_struct work;
8534+ struct mac802154_priv *priv;
8535+ u8 page;
8536+ u8 chan;
8537+};
8538+
8539+static void mac802154_xmit_worker(struct work_struct *work)
8540+{
8541+ struct xmit_work *xw = container_of(work, struct xmit_work, work);
8542+ int res;
8543+
8544+ BUG_ON(xw->chan == (u8)-1);
8545+
8546+ mutex_lock(&xw->priv->phy->pib_lock);
8547+ if (xw->priv->phy->current_channel != xw->chan ||
8548+ xw->priv->phy->current_page != xw->page) {
8549+ res = xw->priv->ops->set_channel(&xw->priv->hw,
8550+ xw->page,
8551+ xw->chan);
8552+ if (res) {
8553+ pr_debug("set_channel failed\n");
8554+ goto out;
8555+ }
8556+ }
8557+
8558+ res = xw->priv->ops->xmit(&xw->priv->hw, xw->skb);
8559+
8560+out:
8561+ mutex_unlock(&xw->priv->phy->pib_lock);
8562+
8563+ /* FIXME: result processing and/or requeue!!! */
8564+ dev_kfree_skb(xw->skb);
8565+
8566+ kfree(xw);
8567+}
8568+
8569+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
8570+ u8 page, u8 chan)
8571+{
8572+ struct xmit_work *work;
8573+
8574+ if (WARN_ON(!(priv->phy->channels_supported[page] &
8575+ (1 << chan))))
8576+ return NETDEV_TX_OK;
8577+
8578+ mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
8579+
8580+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
8581+ u16 crc = crc_ccitt(0, skb->data, skb->len);
8582+ u8 *data = skb_put(skb, 2);
8583+ data[0] = crc & 0xff;
8584+ data[1] = crc >> 8;
8585+ }
8586+
8587+ if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
8588+ dev_kfree_skb(skb);
8589+ return NETDEV_TX_OK;
8590+ }
8591+
8592+ work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
8593+ if (!work)
8594+ return NETDEV_TX_BUSY;
8595+
8596+ INIT_WORK(&work->work, mac802154_xmit_worker);
8597+ work->skb = skb;
8598+ work->priv = priv;
8599+ work->page = page;
8600+ work->chan = chan;
8601+
8602+ queue_work(priv->dev_workqueue, &work->work);
8603+
8604+ return NETDEV_TX_OK;
8605+}
8606diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
8607new file mode 100644
8608index 0000000..6393888
8609--- /dev/null
8610@@ -0,0 +1,630 @@
8611+/*
8612+ * Copyright 2007, 2008, 2009 Siemens AG
8613+ *
8614+ * This program is free software; you can redistribute it and/or modify
8615+ * it under the terms of the GNU General Public License version 2
8616+ * as published by the Free Software Foundation.
8617+ *
8618+ * This program is distributed in the hope that it will be useful,
8619+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8620+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8621+ * GNU General Public License for more details.
8622+ *
8623+ * You should have received a copy of the GNU General Public License along
8624+ * with this program; if not, write to the Free Software Foundation, Inc.,
8625+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8626+ *
8627+ * Written by:
8628+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8629+ * Sergey Lapin <slapin@ossfans.org>
8630+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8631+ */
8632+
8633+#include <linux/netdevice.h>
8634+#include <linux/capability.h>
8635+#include <linux/module.h>
8636+#include <linux/if_arp.h>
8637+#include <linux/rculist.h>
8638+#include <linux/random.h>
8639+#include <linux/crc-ccitt.h>
8640+#include <linux/nl802154.h>
8641+
8642+#include <net/rtnetlink.h>
8643+#include <net/af_ieee802154.h>
8644+#include <net/mac802154.h>
8645+#include <net/ieee802154_netdev.h>
8646+#include <net/ieee802154.h>
8647+#include <net/wpan-phy.h>
8648+
8649+#include "mac802154.h"
8650+#include "mib.h"
8651+
8652+static netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
8653+{
8654+ struct mac802154_sub_if_data *priv;
8655+ u8 chan, page;
8656+
8657+ priv = netdev_priv(dev);
8658+
8659+ spin_lock_bh(&priv->mib_lock);
8660+ chan = priv->chan;
8661+ page = priv->page;
8662+ spin_unlock_bh(&priv->mib_lock);
8663+
8664+ if (chan == (u8)-1) /* not init */
8665+ return NETDEV_TX_OK;
8666+
8667+ BUG_ON(page >= WPAN_NUM_PAGES);
8668+ BUG_ON(chan >= 27);
8669+
8670+ skb->skb_iif = dev->ifindex;
8671+ dev->stats.tx_packets++;
8672+ dev->stats.tx_bytes += skb->len;
8673+
8674+ return mac802154_tx(priv->hw, skb, page, chan);
8675+}
8676+
8677+static int mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr,
8678+ int cmd)
8679+{
8680+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
8681+ struct sockaddr_ieee802154 *sa =
8682+ (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
8683+ int err = -ENOIOCTLCMD;
8684+
8685+ spin_lock_bh(&priv->mib_lock);
8686+
8687+ switch (cmd) {
8688+ case SIOCGIFADDR:
8689+ if (priv->pan_id == IEEE802154_PANID_BROADCAST ||
8690+ priv->short_addr == IEEE802154_ADDR_BROADCAST) {
8691+ err = -EADDRNOTAVAIL;
8692+ break;
8693+ }
8694+
8695+ sa->family = AF_IEEE802154;
8696+ sa->addr.addr_type = IEEE802154_ADDR_SHORT;
8697+ sa->addr.pan_id = priv->pan_id;
8698+ sa->addr.short_addr = priv->short_addr;
8699+
8700+ err = 0;
8701+ break;
8702+ case SIOCSIFADDR:
8703+ dev_warn(&dev->dev,
8704+ "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n");
8705+ if (sa->family != AF_IEEE802154 ||
8706+ sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
8707+ sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
8708+ sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
8709+ sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
8710+ err = -EINVAL;
8711+ break;
8712+ }
8713+
8714+ priv->pan_id = sa->addr.pan_id;
8715+ priv->short_addr = sa->addr.short_addr;
8716+ err = 0;
8717+ break;
8718+ }
8719+ spin_unlock_bh(&priv->mib_lock);
8720+ return err;
8721+}
8722+
8723+static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
8724+{
8725+ struct sockaddr *addr = p;
8726+
8727+ if (netif_running(dev))
8728+ return -EBUSY;
8729+ /* FIXME: validate addr */
8730+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
8731+ mac802154_dev_set_ieee_addr(dev);
8732+ return 0;
8733+}
8734+
8735+static void mac802154_haddr_copy_swap(u8 *dest, const u8 *src)
8736+{
8737+ int i;
8738+ for (i = 0; i < IEEE802154_ADDR_LEN; i++)
8739+ dest[IEEE802154_ADDR_LEN - i - 1] = src[i];
8740+}
8741+
8742+static int mac802154_header_create(struct sk_buff *skb,
8743+ struct net_device *dev,
8744+ unsigned short type, const void *_daddr,
8745+ const void *_saddr, unsigned len)
8746+{
8747+ u8 head[24] = {};
8748+ int pos = 0;
8749+
8750+ u16 fc;
8751+ const struct ieee802154_addr *saddr = _saddr;
8752+ const struct ieee802154_addr *daddr = _daddr;
8753+ struct ieee802154_addr dev_addr;
8754+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
8755+
8756+ fc = mac_cb_type(skb);
8757+ if (mac_cb_is_ackreq(skb))
8758+ fc |= IEEE802154_FC_ACK_REQ;
8759+
8760+ pos = 2;
8761+
8762+ head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
8763+
8764+ if (!daddr)
8765+ return -EINVAL;
8766+
8767+ if (!saddr) {
8768+ spin_lock_bh(&priv->mib_lock);
8769+ if (priv->short_addr == IEEE802154_ADDR_BROADCAST ||
8770+ priv->short_addr == IEEE802154_ADDR_UNDEF ||
8771+ priv->pan_id == IEEE802154_PANID_BROADCAST) {
8772+ dev_addr.addr_type = IEEE802154_ADDR_LONG;
8773+ memcpy(dev_addr.hwaddr, dev->dev_addr,
8774+ IEEE802154_ADDR_LEN);
8775+ } else {
8776+ dev_addr.addr_type = IEEE802154_ADDR_SHORT;
8777+ dev_addr.short_addr = priv->short_addr;
8778+ }
8779+
8780+ dev_addr.pan_id = priv->pan_id;
8781+ saddr = &dev_addr;
8782+
8783+ spin_unlock_bh(&priv->mib_lock);
8784+ }
8785+
8786+ if (daddr->addr_type != IEEE802154_ADDR_NONE) {
8787+ fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
8788+
8789+ head[pos++] = daddr->pan_id & 0xff;
8790+ head[pos++] = daddr->pan_id >> 8;
8791+
8792+ if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
8793+ head[pos++] = daddr->short_addr & 0xff;
8794+ head[pos++] = daddr->short_addr >> 8;
8795+ } else {
8796+ mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
8797+ pos += IEEE802154_ADDR_LEN;
8798+ }
8799+ }
8800+
8801+ if (saddr->addr_type != IEEE802154_ADDR_NONE) {
8802+ fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
8803+
8804+ if ((saddr->pan_id == daddr->pan_id) &&
8805+ (saddr->pan_id != IEEE802154_PANID_BROADCAST))
8806+ /* PANID compression/ intra PAN */
8807+ fc |= IEEE802154_FC_INTRA_PAN;
8808+ else {
8809+ head[pos++] = saddr->pan_id & 0xff;
8810+ head[pos++] = saddr->pan_id >> 8;
8811+ }
8812+
8813+ if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
8814+ head[pos++] = saddr->short_addr & 0xff;
8815+ head[pos++] = saddr->short_addr >> 8;
8816+ } else {
8817+ mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
8818+ pos += IEEE802154_ADDR_LEN;
8819+ }
8820+ }
8821+
8822+ head[0] = fc;
8823+ head[1] = fc >> 8;
8824+
8825+ memcpy(skb_push(skb, pos), head, pos);
8826+
8827+ return pos;
8828+}
8829+
8830+static int mac802154_header_parse(const struct sk_buff *skb,
8831+ unsigned char *haddr)
8832+{
8833+ const u8 *hdr = skb_mac_header(skb), *tail = skb_tail_pointer(skb);
8834+ struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
8835+ u16 fc;
8836+ int da_type;
8837+
8838+ if (hdr + 3 > tail)
8839+ goto malformed;
8840+
8841+ fc = hdr[0] | (hdr[1] << 8);
8842+
8843+ hdr += 3;
8844+
8845+ da_type = IEEE802154_FC_DAMODE(fc);
8846+ addr->addr_type = IEEE802154_FC_SAMODE(fc);
8847+
8848+ switch (da_type) {
8849+ case IEEE802154_ADDR_NONE:
8850+ if (fc & IEEE802154_FC_INTRA_PAN)
8851+ goto malformed;
8852+ break;
8853+
8854+ case IEEE802154_ADDR_LONG:
8855+ if (hdr + 2 > tail)
8856+ goto malformed;
8857+ if (fc & IEEE802154_FC_INTRA_PAN) {
8858+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8859+ hdr += 2;
8860+ }
8861+
8862+ if (hdr + IEEE802154_ADDR_LEN > tail)
8863+ goto malformed;
8864+ hdr += IEEE802154_ADDR_LEN;
8865+ break;
8866+
8867+ case IEEE802154_ADDR_SHORT:
8868+ if (hdr + 2 > tail)
8869+ goto malformed;
8870+ if (fc & IEEE802154_FC_INTRA_PAN) {
8871+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8872+ hdr += 2;
8873+ }
8874+
8875+ if (hdr + 2 > tail)
8876+ goto malformed;
8877+ hdr += 2;
8878+ break;
8879+
8880+ default:
8881+ goto malformed;
8882+
8883+ }
8884+
8885+ switch (addr->addr_type) {
8886+ case IEEE802154_ADDR_NONE:
8887+ break;
8888+
8889+ case IEEE802154_ADDR_LONG:
8890+ if (hdr + 2 > tail)
8891+ goto malformed;
8892+ if (!(fc & IEEE802154_FC_INTRA_PAN)) {
8893+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8894+ hdr += 2;
8895+ }
8896+
8897+ if (hdr + IEEE802154_ADDR_LEN > tail)
8898+ goto malformed;
8899+ mac802154_haddr_copy_swap(addr->hwaddr, hdr);
8900+ hdr += IEEE802154_ADDR_LEN;
8901+ break;
8902+
8903+ case IEEE802154_ADDR_SHORT:
8904+ if (hdr + 2 > tail)
8905+ goto malformed;
8906+ if (!(fc & IEEE802154_FC_INTRA_PAN)) {
8907+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8908+ hdr += 2;
8909+ }
8910+
8911+ if (hdr + 2 > tail)
8912+ goto malformed;
8913+ addr->short_addr = hdr[0] | (hdr[1] << 8);
8914+ hdr += 2;
8915+ break;
8916+
8917+ default:
8918+ goto malformed;
8919+
8920+ }
8921+
8922+ return sizeof(struct ieee802154_addr);
8923+
8924+malformed:
8925+ pr_debug("malformed packet\n");
8926+ return 0;
8927+}
8928+
8929+static struct header_ops mac802154_header_ops = {
8930+ .create = mac802154_header_create,
8931+ .parse = mac802154_header_parse,
8932+};
8933+
8934+static const struct net_device_ops mac802154_wpan_ops = {
8935+ .ndo_open = mac802154_slave_open,
8936+ .ndo_stop = mac802154_slave_close,
8937+ .ndo_start_xmit = mac802154_wpan_xmit,
8938+ .ndo_do_ioctl = mac802154_wpan_ioctl,
8939+ .ndo_set_mac_address = mac802154_wpan_mac_addr,
8940+};
8941+
8942+void mac802154_wpan_setup(struct net_device *dev)
8943+{
8944+ struct mac802154_sub_if_data *priv;
8945+
8946+ dev->addr_len = IEEE802154_ADDR_LEN;
8947+ memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
8948+ dev->features = NETIF_F_NO_CSUM;
8949+ dev->hard_header_len = 2 + 1 + 20 + 14;
8950+ dev->header_ops = &mac802154_header_ops;
8951+ dev->needed_tailroom = 2; /* FCS */
8952+ dev->mtu = 127;
8953+ dev->tx_queue_len = 10;
8954+ dev->type = ARPHRD_IEEE802154;
8955+ dev->flags = IFF_NOARP | IFF_BROADCAST;
8956+ dev->watchdog_timeo = 0;
8957+
8958+ dev->destructor = free_netdev;
8959+ dev->netdev_ops = &mac802154_wpan_ops;
8960+ dev->ml_priv = &mac802154_mlme_wpan.wpan_ops;
8961+
8962+ priv = netdev_priv(dev);
8963+ priv->type = IEEE802154_DEV_WPAN;
8964+
8965+ priv->chan = -1; /* not initialized */
8966+ priv->page = 0; /* for compat */
8967+
8968+ spin_lock_init(&priv->mib_lock);
8969+
8970+ get_random_bytes(&priv->bsn, 1);
8971+ get_random_bytes(&priv->dsn, 1);
8972+
8973+ priv->pan_id = IEEE802154_PANID_BROADCAST;
8974+ priv->short_addr = IEEE802154_ADDR_BROADCAST;
8975+}
8976+
8977+static int mac802154_process_ack(struct net_device *dev, struct sk_buff *skb)
8978+{
8979+ pr_debug("got ACK for SEQ=%d\n", mac_cb(skb)->seq);
8980+
8981+ kfree_skb(skb);
8982+ return NET_RX_SUCCESS;
8983+}
8984+
8985+static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
8986+{
8987+ if (in_interrupt())
8988+ return netif_rx(skb);
8989+ else
8990+ return netif_rx_ni(skb);
8991+}
8992+
8993+static int mac802154_subif_frame(struct mac802154_sub_if_data *sdata,
8994+ struct sk_buff *skb)
8995+{
8996+ pr_debug("%s Getting packet via slave interface %s\n",
8997+ __func__, sdata->dev->name);
8998+
8999+ spin_lock_bh(&sdata->mib_lock);
9000+
9001+ switch (mac_cb(skb)->da.addr_type) {
9002+ case IEEE802154_ADDR_NONE:
9003+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE)
9004+ /* FIXME: check if we are PAN coordinator :) */
9005+ skb->pkt_type = PACKET_OTHERHOST;
9006+ else
9007+ /* ACK comes with both addresses empty */
9008+ skb->pkt_type = PACKET_HOST;
9009+ break;
9010+ case IEEE802154_ADDR_LONG:
9011+ if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
9012+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
9013+ skb->pkt_type = PACKET_OTHERHOST;
9014+ else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr,
9015+ IEEE802154_ADDR_LEN))
9016+ skb->pkt_type = PACKET_HOST;
9017+ else
9018+ skb->pkt_type = PACKET_OTHERHOST;
9019+ break;
9020+ case IEEE802154_ADDR_SHORT:
9021+ if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
9022+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
9023+ skb->pkt_type = PACKET_OTHERHOST;
9024+ else if (mac_cb(skb)->da.short_addr == sdata->short_addr)
9025+ skb->pkt_type = PACKET_HOST;
9026+ else if (mac_cb(skb)->da.short_addr ==
9027+ IEEE802154_ADDR_BROADCAST)
9028+ skb->pkt_type = PACKET_BROADCAST;
9029+ else
9030+ skb->pkt_type = PACKET_OTHERHOST;
9031+ break;
9032+ }
9033+
9034+ spin_unlock_bh(&sdata->mib_lock);
9035+
9036+ skb->dev = sdata->dev;
9037+
9038+ if (skb->pkt_type == PACKET_HOST && mac_cb_is_ackreq(skb) &&
9039+ !(sdata->hw->hw.flags & IEEE802154_HW_AACK))
9040+ dev_warn(&sdata->dev->dev,
9041+ "ACK requested, however AACK not supported.\n");
9042+
9043+ switch (mac_cb_type(skb)) {
9044+ case IEEE802154_FC_TYPE_BEACON:
9045+ return mac802154_process_beacon(sdata->dev, skb);
9046+ case IEEE802154_FC_TYPE_ACK:
9047+ return mac802154_process_ack(sdata->dev, skb);
9048+ case IEEE802154_FC_TYPE_MAC_CMD:
9049+ return mac802154_process_cmd(sdata->dev, skb);
9050+ case IEEE802154_FC_TYPE_DATA:
9051+ return mac802154_process_data(sdata->dev, skb);
9052+ default:
9053+ pr_warning("ieee802154: Bad frame received (type = %d)\n",
9054+ mac_cb_type(skb));
9055+ kfree_skb(skb);
9056+ return NET_RX_DROP;
9057+ }
9058+}
9059+
9060+static u8 fetch_skb_u8(struct sk_buff *skb)
9061+{
9062+ u8 ret;
9063+
9064+ BUG_ON(skb->len < 1);
9065+
9066+ ret = skb->data[0];
9067+ skb_pull(skb, 1);
9068+
9069+ return ret;
9070+}
9071+
9072+static u16 fetch_skb_u16(struct sk_buff *skb)
9073+{
9074+ u16 ret;
9075+
9076+ BUG_ON(skb->len < 2);
9077+
9078+ ret = skb->data[0] + (skb->data[1] * 256);
9079+ skb_pull(skb, 2);
9080+ return ret;
9081+}
9082+
9083+static void fetch_skb_u64(struct sk_buff *skb, u8 *dest)
9084+{
9085+ int i;
9086+
9087+ BUG_ON(skb->len < IEEE802154_ADDR_LEN);
9088+
9089+ for (i = 0; i < IEEE802154_ADDR_LEN; i++)
9090+ dest[IEEE802154_ADDR_LEN - i - 1] = skb->data[i];
9091+ skb_pull(skb, IEEE802154_ADDR_LEN);
9092+}
9093+
9094+#define IEEE802154_FETCH_U8(skb, var) \
9095+ do { \
9096+ if (skb->len < 1) \
9097+ goto exit_error; \
9098+ var = fetch_skb_u8(skb); \
9099+ } while (0)
9100+
9101+#define IEEE802154_FETCH_U16(skb, var) \
9102+ do { \
9103+ if (skb->len < 2) \
9104+ goto exit_error; \
9105+ var = fetch_skb_u16(skb); \
9106+ } while (0)
9107+
9108+#define IEEE802154_FETCH_U64(skb, var) \
9109+ do { \
9110+ if (skb->len < IEEE802154_ADDR_LEN) \
9111+ goto exit_error; \
9112+ fetch_skb_u64(skb, var); \
9113+ } while (0)
9114+
9115+static int parse_frame_start(struct sk_buff *skb)
9116+{
9117+ u8 *head = skb->data;
9118+ u16 fc;
9119+
9120+ if (skb->len < 3) {
9121+ pr_debug("frame size %d bytes is too short\n", skb->len);
9122+ return -EINVAL;
9123+ }
9124+
9125+ IEEE802154_FETCH_U16(skb, fc);
9126+ IEEE802154_FETCH_U8(skb, mac_cb(skb)->seq);
9127+
9128+ pr_debug("%s: %04x dsn%02x\n", __func__, fc, head[2]);
9129+
9130+ mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc);
9131+
9132+ if (fc & IEEE802154_FC_ACK_REQ) {
9133+ pr_debug("%s(): ACKNOWLEDGE required\n", __func__);
9134+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
9135+ }
9136+
9137+ if (fc & IEEE802154_FC_SECEN)
9138+ mac_cb(skb)->flags |= MAC_CB_FLAG_SECEN;
9139+
9140+ if (fc & IEEE802154_FC_INTRA_PAN)
9141+ mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN;
9142+
9143+ /* TODO */
9144+ if (mac_cb_is_secen(skb)) {
9145+ pr_info("security support is not implemented\n");
9146+ return -EINVAL;
9147+ }
9148+
9149+ mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
9150+ if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_NONE)
9151+ pr_debug("%s(): src addr_type is NONE\n", __func__);
9152+
9153+ mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
9154+ if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_NONE)
9155+ pr_debug("%s(): dst addr_type is NONE\n", __func__);
9156+
9157+ if (IEEE802154_FC_TYPE(fc) == IEEE802154_FC_TYPE_ACK) {
9158+ /* ACK can only have NONE-type addresses */
9159+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE ||
9160+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE)
9161+ return -EINVAL;
9162+ }
9163+
9164+ if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) {
9165+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->da.pan_id);
9166+
9167+ if (mac_cb_is_intrapan(skb)) { /* ! panid compress */
9168+ pr_debug("%s(): src IEEE802154_FC_INTRA_PAN\n",
9169+ __func__);
9170+ mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
9171+ pr_debug("%s(): src PAN address %04x\n",
9172+ __func__, mac_cb(skb)->sa.pan_id);
9173+ }
9174+
9175+ pr_debug("%s(): dst PAN address %04x\n",
9176+ __func__, mac_cb(skb)->da.pan_id);
9177+
9178+ if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) {
9179+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->da.short_addr);
9180+ pr_debug("%s(): dst SHORT address %04x\n",
9181+ __func__, mac_cb(skb)->da.short_addr);
9182+
9183+ } else {
9184+ IEEE802154_FETCH_U64(skb, mac_cb(skb)->da.hwaddr);
9185+ pr_debug("%s(): dst hardware addr\n", __func__);
9186+ }
9187+ }
9188+
9189+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) {
9190+ pr_debug("%s(): got src non-NONE address\n", __func__);
9191+ if (!(mac_cb_is_intrapan(skb))) { /* ! panid compress */
9192+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->sa.pan_id);
9193+ pr_debug("%s(): src IEEE802154_FC_INTRA_PAN\n",
9194+ __func__);
9195+ }
9196+
9197+ if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
9198+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->sa.short_addr);
9199+ pr_debug("%s(): src IEEE802154_ADDR_SHORT\n",
9200+ __func__);
9201+ } else {
9202+ IEEE802154_FETCH_U64(skb, mac_cb(skb)->sa.hwaddr);
9203+ pr_debug("%s(): src hardware addr\n", __func__);
9204+ }
9205+ }
9206+
9207+ return 0;
9208+
9209+exit_error:
9210+ return -EINVAL;
9211+}
9212+
9213+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
9214+{
9215+ int ret;
9216+ struct mac802154_sub_if_data *sdata;
9217+ struct sk_buff *skb2;
9218+
9219+ ret = parse_frame_start(skb); /* 3 bytes pulled after this */
9220+ if (ret) {
9221+ pr_debug("%s(): Got invalid frame\n", __func__);
9222+ return;
9223+ }
9224+
9225+ pr_debug("%s() frame %d\n", __func__, mac_cb_type(skb));
9226+
9227+ rcu_read_lock();
9228+ list_for_each_entry_rcu(sdata, &priv->slaves, list)
9229+ {
9230+ if (sdata->type != IEEE802154_DEV_WPAN)
9231+ continue;
9232+
9233+ skb2 = skb_clone(skb, GFP_ATOMIC);
9234+ if (skb2)
9235+ mac802154_subif_frame(sdata, skb2);
9236+ }
9237+
9238+ rcu_read_unlock();
9239+}
9240+
9241diff --git a/net/zigbee/Kconfig b/net/zigbee/Kconfig
9242new file mode 100644
9243index 0000000..85134a9
9244--- /dev/null
9245@@ -0,0 +1,7 @@
9246+config ZIGBEE
9247+ tristate "ZigBee Low-Rate Wireless Personal Area Networks support (EXPERIMENTAL)"
9248+ depends on EXPERIMENTAL && BROKEN
9249+ ---help---
9250+
9251+ Say Y here to compile ZigBee support into the kernel or say M to
9252+ compile it as modules.
9253diff --git a/net/zigbee/Makefile b/net/zigbee/Makefile
9254new file mode 100644
9255index 0000000..8c2eee5
9256--- /dev/null
9257@@ -0,0 +1,5 @@
9258+obj-$(CONFIG_ZIGBEE) += af_zb.o
9259+
9260+af_zb-objs := af_zigbee.o dgram.o
9261+
9262+EXTRA_CFLAGS += -Wall -DEXPORT_SYMTAB -DCONFIG_FFD -DCONFIG_ZIGBEE_DEBUG -DIEEE80215_DEBUG -DDEBUG
9263diff --git a/net/zigbee/af_zigbee.c b/net/zigbee/af_zigbee.c
9264new file mode 100644
9265index 0000000..820d668
9266--- /dev/null
9267@@ -0,0 +1,285 @@
9268+/*
9269+ * ZigBee socket interface
9270+ *
9271+ * Copyright 2008, 2009 Siemens AG
9272+ *
9273+ * This program is free software; you can redistribute it and/or modify
9274+ * it under the terms of the GNU General Public License version 2
9275+ * as published by the Free Software Foundation.
9276+ *
9277+ * This program is distributed in the hope that it will be useful,
9278+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9279+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9280+ * GNU General Public License for more details.
9281+ *
9282+ * You should have received a copy of the GNU General Public License along
9283+ * with this program; if not, write to the Free Software Foundation, Inc.,
9284+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
9285+ *
9286+ * Written by:
9287+ * Sergey Lapin <slapin@ossfans.org>
9288+ * Maxim Yu. Osipov <Maksim.Osipov@siemens.com>
9289+ */
9290+#include <linux/net.h>
9291+#include <linux/capability.h>
9292+#include <linux/module.h>
9293+#include <linux/if_arp.h>
9294+#include <linux/if.h>
9295+#include <linux/termios.h> /* For TIOCOUTQ/INQ */
9296+#include <linux/list.h>
9297+#include <net/datalink.h>
9298+#include <net/psnap.h>
9299+#include <net/sock.h>
9300+#include <net/tcp_states.h>
9301+#include <net/route.h>
9302+
9303+//#include <net/ieee80215/af_ieee80215.h>
9304+#include <net/zigbee/af_zigbee.h>
9305+#include <net/zigbee/nwk.h>
9306+
9307+#define DBG_DUMP(data, len) { \
9308+ int i; \
9309+ pr_debug("file %s: function: %s: data: len %d:\n", __FILE__, __func__, len); \
9310+ for (i = 0; i < len; i++) {\
9311+ pr_debug("%02x: %02x\n", i, (data)[i]); \
9312+ } \
9313+}
9314+
9315+static int zb_sock_release(struct socket *sock)
9316+{
9317+ struct sock *sk = sock->sk;
9318+
9319+ if (sk) {
9320+ sock->sk = NULL;
9321+ sk->sk_prot->close(sk, 0);
9322+ }
9323+ return 0;
9324+}
9325+static int zb_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
9326+{
9327+ struct sock *sk = sock->sk;
9328+
9329+ return sk->sk_prot->sendmsg(iocb, sk, msg, len);
9330+}
9331+
9332+static int zb_sock_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
9333+{
9334+ struct sock *sk = sock->sk;
9335+
9336+ if (sk->sk_prot->bind)
9337+ return sk->sk_prot->bind(sk, uaddr, addr_len);
9338+
9339+ return sock_no_bind(sock, uaddr, addr_len);
9340+}
9341+
9342+static int zb_sock_connect(struct socket *sock, struct sockaddr *uaddr,
9343+ int addr_len, int flags)
9344+{
9345+ struct sock *sk = sock->sk;
9346+
9347+ if (uaddr->sa_family == AF_UNSPEC)
9348+ return sk->sk_prot->disconnect(sk, flags);
9349+
9350+ return sk->sk_prot->connect(sk, uaddr, addr_len);
9351+}
9352+
9353+#if 0
9354+static int zb_dev_ioctl(struct sock *sk, struct ifreq __user *arg, unsigned int cmd)
9355+{
9356+ struct ifreq ifr;
9357+ int ret = -EINVAL;
9358+ struct net_device *dev;
9359+
9360+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
9361+ return -EFAULT;
9362+
9363+ ifr.ifr_name[IFNAMSIZ-1] = 0;
9364+
9365+ dev_load(sock_net(sk), ifr.ifr_name);
9366+ dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
9367+ if (dev->type == ARPHRD_ZIGBEE || dev->type == ARPHRD_ZIGBEE_PHY)
9368+ ret = dev->do_ioctl(dev, &ifr, cmd);
9369+
9370+ if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
9371+ ret = -EFAULT;
9372+ dev_put(dev);
9373+
9374+ return ret;
9375+}
9376+#endif
9377+
9378+static int zb_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
9379+{
9380+ struct sock *sk = sock->sk;
9381+
9382+ switch (cmd) {
9383+ case SIOCGSTAMP:
9384+ return sock_get_timestamp(sk, (struct timeval __user *)arg);
9385+ case SIOCGSTAMPNS:
9386+ return sock_get_timestampns(sk, (struct timespec __user *)arg);
9387+#if 0
9388+ case SIOCGIFADDR:
9389+ case SIOCSIFADDR:
9390+ return zb_dev_ioctl(sk, (struct ifreq __user *)arg, cmd);
9391+#endif
9392+ default:
9393+ if (!sk->sk_prot->ioctl)
9394+ return -ENOIOCTLCMD;
9395+ return sk->sk_prot->ioctl(sk, cmd, arg);
9396+ }
9397+}
9398+
9399+static const struct proto_ops zb_dgram_ops = {
9400+ .family = PF_ZIGBEE,
9401+ .owner = THIS_MODULE,
9402+ .release = zb_sock_release,
9403+ .bind = zb_sock_bind,
9404+ .connect = zb_sock_connect,
9405+ .socketpair = sock_no_socketpair,
9406+ .accept = sock_no_accept,
9407+ .getname = sock_no_getname,
9408+ .poll = datagram_poll,
9409+ .ioctl = zb_sock_ioctl,
9410+ .listen = sock_no_listen,
9411+ .shutdown = sock_no_shutdown,
9412+ .setsockopt = sock_common_setsockopt,
9413+ .getsockopt = sock_common_getsockopt,
9414+ .sendmsg = zb_sock_sendmsg,
9415+ .recvmsg = sock_common_recvmsg,
9416+ .mmap = sock_no_mmap,
9417+ .sendpage = sock_no_sendpage,
9418+#ifdef CONFIG_COMPAT
9419+ .compat_setsockopt = compat_sock_common_setsockopt,
9420+ .compat_getsockopt = compat_sock_common_getsockopt,
9421+#endif
9422+};
9423+
9424+
9425+/*
9426+ * Create a socket. Initialise the socket, blank the addresses
9427+ * set the state.
9428+ */
9429+static int zb_create(struct net *net, struct socket *sock, int protocol)
9430+{
9431+ struct sock *sk;
9432+ int rc;
9433+ struct proto *proto;
9434+ const struct proto_ops *ops;
9435+
9436+ // FIXME: init_net
9437+ if (net != &init_net)
9438+ return -EAFNOSUPPORT;
9439+
9440+ if (sock->type == SOCK_DGRAM) {
9441+ proto = &zb_dgram_prot;
9442+ ops = &zb_dgram_ops;
9443+ }
9444+ else {
9445+ rc = -ESOCKTNOSUPPORT;
9446+ goto out;
9447+ }
9448+
9449+ rc = -ENOMEM;
9450+ sk = sk_alloc(net, PF_ZIGBEE, GFP_KERNEL, proto);
9451+ if (!sk)
9452+ goto out;
9453+ rc = 0;
9454+
9455+ sock->ops = ops;
9456+
9457+ sock_init_data(sock, sk);
9458+ // FIXME: sk->sk_destruct
9459+ sk->sk_family = PF_ZIGBEE;
9460+
9461+#if 0
9462+ /* Checksums on by default */
9463+ // FIXME:
9464+ sock_set_flag(sk, SOCK_ZAPPED);
9465+
9466+ // FIXME:
9467+ if (sk->sk_prot->hash)
9468+ sk->sk_prot->hash(sk);
9469+#endif
9470+
9471+ if (sk->sk_prot->init) {
9472+ rc = sk->sk_prot->init(sk);
9473+ if (rc)
9474+ sk_common_release(sk);
9475+ }
9476+out:
9477+ return rc;
9478+}
9479+
9480+static struct net_proto_family zb_family_ops = {
9481+ .family = PF_ZIGBEE,
9482+ .create = zb_create,
9483+ .owner = THIS_MODULE,
9484+};
9485+
9486+/*
9487+ * Main ZigBEE NWK receive routine.
9488+ */
9489+static int zb_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
9490+{
9491+ struct nwkhdr *nwkh;
9492+ u32 len;
9493+
9494+ DBG_DUMP(skb->data, skb->len);
9495+ pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
9496+ // FIXME: init_net
9497+ if (!net_eq(dev_net(dev), &init_net))
9498+ goto drop;
9499+
9500+ zb_raw_deliver(dev, skb);
9501+
9502+ if (skb->pkt_type != PACKET_OTHERHOST)
9503+ return zb_dgram_deliver(dev, skb);
9504+
9505+drop:
9506+ kfree_skb(skb);
9507+ return NET_RX_DROP;
9508+}
9509+
9510+
9511+static struct packet_type zb_packet_type = {
9512+ .type = __constant_htons(ETH_P_ZIGBEE),
9513+ .func = zb_rcv,
9514+};
9515+
9516+static int __init af_zb_init(void)
9517+{
9518+ int rc = -EINVAL;
9519+
9520+ rc = proto_register(&zb_dgram_prot, 1);
9521+ if (rc)
9522+ goto err;
9523+
9524+ /* Tell SOCKET that we are alive */
9525+ rc = sock_register(&zb_family_ops);
9526+
9527+ if (rc)
9528+ goto err;
9529+
9530+ dev_add_pack(&zb_packet_type);
9531+
9532+ rc = 0;
9533+ goto out;
9534+
9535+err:
9536+ proto_unregister(&zb_dgram_prot);
9537+out:
9538+ return rc;
9539+}
9540+
9541+static void af_zb_remove(void)
9542+{
9543+ dev_remove_pack(&zb_packet_type);
9544+ sock_unregister(PF_ZIGBEE);
9545+ proto_unregister(&zb_dgram_prot);
9546+}
9547+
9548+module_init(af_zb_init);
9549+module_exit(af_zb_remove);
9550+
9551+MODULE_LICENSE("GPL");
9552+MODULE_ALIAS_NETPROTO(PF_ZIGBEE);
9553diff --git a/net/zigbee/dgram.c b/net/zigbee/dgram.c
9554new file mode 100644
9555index 0000000..4d9b682
9556--- /dev/null
9557@@ -0,0 +1,401 @@
9558+/*
9559+ * ZigBee socket interface
9560+ *
9561+ * Copyright 2008, 2009 Siemens AG
9562+ *
9563+ * This program is free software; you can redistribute it and/or modify
9564+ * it under the terms of the GNU General Public License version 2
9565+ * as published by the Free Software Foundation.
9566+ *
9567+ * This program is distributed in the hope that it will be useful,
9568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9570+ * GNU General Public License for more details.
9571+ *
9572+ * You should have received a copy of the GNU General Public License along
9573+ * with this program; if not, write to the Free Software Foundation, Inc.,
9574+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
9575+ *
9576+ * Written by:
9577+ * Sergey Lapin <slapin@ossfans.org>
9578+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
9579+ * Maxim Yu. Osipov <Maksim.Osipov@siemens.com>
9580+ */
9581+
9582+#include <linux/net.h>
9583+#include <linux/module.h>
9584+#include <linux/if_arp.h>
9585+#include <linux/list.h>
9586+#include <net/sock.h>
9587+//#include <net/ieee80215/netdev.h>
9588+//#include <net/ieee80215/af_ieee80215.h>
9589+//#include <net/ieee80215/mac_def.h>
9590+#include <net/zigbee/nwk.h>
9591+#include <asm/ioctls.h>
9592+
9593+static HLIST_HEAD(dgram_head);
9594+static DEFINE_RWLOCK(dgram_lock);
9595+
9596+struct dgram_sock {
9597+ struct sock sk;
9598+
9599+ int bound;
9600+ struct ieee80215_addr src_addr;
9601+ struct ieee80215_addr dst_addr;
9602+};
9603+
9604+static void dgram_hash(struct sock *sk)
9605+{
9606+ write_lock_bh(&dgram_lock);
9607+ sk_add_node(sk, &dgram_head);
9608+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
9609+ write_unlock_bh(&dgram_lock);
9610+}
9611+
9612+static void dgram_unhash(struct sock *sk)
9613+{
9614+ write_lock_bh(&dgram_lock);
9615+ if (sk_del_node_init(sk))
9616+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
9617+ write_unlock_bh(&dgram_lock);
9618+}
9619+
9620+static int dgram_init(struct sock *sk)
9621+{
9622+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9623+
9624+ ro->dst_addr.addr_type = IEEE80215_ADDR_SHORT;
9625+// ro->dst_addr.pan_id = 0xffff;
9626+ ro->dst_addr.short_addr = 0xffff;
9627+ return 0;
9628+}
9629+
9630+static void dgram_close(struct sock *sk, long timeout)
9631+{
9632+ sk_common_release(sk);
9633+}
9634+
9635+static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
9636+{
9637+ struct sockaddr_ieee80215 *addr = (struct sockaddr_ieee80215 *)uaddr;
9638+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9639+ int err = 0;
9640+
9641+ if (ro->bound)
9642+ return -EINVAL;
9643+
9644+ if (len < sizeof(*addr))
9645+ return -EINVAL;
9646+
9647+ if ((addr->family != AF_ZIGBEE) ||
9648+ (addr->addr.addr_type != IEEE80215_ADDR_SHORT))
9649+ return -EINVAL;
9650+
9651+ lock_sock(sk);
9652+ /*
9653+ * FIXME: should check here that address is not already in use
9654+ * Problem that this address is not independent - this is the
9655+ * address of the lower layer
9656+ */
9657+#if 0
9658+ dev = ieee80215_get_dev(sock_net(sk), &addr->addr);
9659+ if (!dev) {
9660+ err = -ENODEV;
9661+ goto out;
9662+ }
9663+
9664+ if (dev->type != ARPHRD_IEEE80215) {
9665+ err = -ENODEV;
9666+ goto out_put;
9667+ }
9668+#endif
9669+ memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee80215_addr));
9670+
9671+ ro->bound = 1;
9672+#if 0
9673+out_put:
9674+ dev_put(dev);
9675+out:
9676+#endif
9677+ release_sock(sk);
9678+
9679+ return err;
9680+}
9681+
9682+static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
9683+{
9684+ switch (cmd) {
9685+ case SIOCOUTQ:
9686+ {
9687+ int amount = atomic_read(&sk->sk_wmem_alloc);
9688+ return put_user(amount, (int __user *)arg);
9689+ }
9690+
9691+ case SIOCINQ:
9692+ {
9693+ struct sk_buff *skb;
9694+ unsigned long amount = 0;
9695+
9696+ spin_lock_bh(&sk->sk_receive_queue.lock);
9697+ skb = skb_peek(&sk->sk_receive_queue);
9698+ if (skb != NULL) {
9699+ /*
9700+ * We will only return the amount
9701+ * of this packet since that is all
9702+ * that will be read.
9703+ */
9704+ amount = skb->len - sizeof(struct nwkhdr);
9705+ }
9706+ spin_unlock_bh(&sk->sk_receive_queue.lock);
9707+ return put_user(amount, (int __user *)arg);
9708+
9709+ }
9710+#if 0
9711+ /* May be implement here the commands */
9712+ case IEEE80215_SIOC_NETWORK_DISCOVERY:
9713+ return ioctl_network_discovery(sk, (struct ieee80215_user_data __user *) arg);
9714+ break;
9715+ case IEEE80215_SIOC_NETWORK_FORMATION:
9716+ return ioctl_network_formation(sk, (struct ieee80215_user_data __user *) arg);
9717+ break;
9718+ case IEEE80215_SIOC_PERMIT_JOINING:
9719+ return ioctl_permit_joining(sk, (struct ieee80215_user_data __user *) arg);
9720+ break;
9721+ case IEEE80215_SIOC_START_ROUTER:
9722+ return ioctl_start_router(sk, (struct ieee80215_user_data __user *) arg);
9723+ break;
9724+ case IEEE80215_SIOC_JOIN:
9725+ return ioctl_mac_join(sk, (struct ieee80215_user_data __user *) arg);
9726+ break;
9727+ case IEEE80215_SIOC_MAC_CMD:
9728+ return ioctl_mac_cmd(sk, (struct ieee80215_user_data __user *) arg);
9729+
9730+ break;
9731+#endif
9732+ default:
9733+ return -ENOIOCTLCMD;
9734+ }
9735+}
9736+
9737+// FIXME: autobind
9738+static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
9739+ int len)
9740+{
9741+ struct sockaddr_ieee80215 *addr = (struct sockaddr_ieee80215 *)uaddr;
9742+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9743+
9744+ int err = 0;
9745+
9746+ if (len < sizeof(*addr))
9747+ return -EINVAL;
9748+
9749+ if ((addr->family != AF_ZIGBEE) ||
9750+ (addr->addr.addr_type != IEEE80215_ADDR_SHORT))
9751+ return -EINVAL;
9752+
9753+ lock_sock(sk);
9754+
9755+ if (!ro->bound) {
9756+ err = -ENETUNREACH;
9757+ goto out;
9758+ }
9759+
9760+ memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee80215_addr));
9761+
9762+out:
9763+ release_sock(sk);
9764+ return err;
9765+}
9766+
9767+static int dgram_disconnect(struct sock *sk, int flags)
9768+{
9769+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9770+
9771+ lock_sock(sk);
9772+
9773+ ro->dst_addr.addr_type = IEEE80215_ADDR_SHORT;
9774+// ro->dst_addr.pan_id = 0xffff;
9775+ ro->dst_addr.short_addr = 0xffff;
9776+
9777+ release_sock(sk);
9778+
9779+ return 0;
9780+}
9781+
9782+static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
9783+ size_t size)
9784+{
9785+ struct net_device *dev;
9786+ unsigned mtu;
9787+ struct sk_buff *skb;
9788+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9789+
9790+ int err;
9791+ struct ieee80215_priv *hw;
9792+
9793+ if (msg->msg_flags & MSG_OOB) {
9794+ pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
9795+ return -EOPNOTSUPP;
9796+ }
9797+
9798+ if (!ro->bound)
9799+ dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE80215);
9800+ else
9801+ dev = ieee80215_get_dev(sock_net(sk), &ro->src_addr);
9802+
9803+ if (!dev) {
9804+ pr_debug("no dev\n");
9805+ return -ENXIO;
9806+ }
9807+ hw = ieee80215_slave_get_hw(dev);
9808+ mtu = dev->mtu;
9809+ pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
9810+
9811+ skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + size, msg->msg_flags & MSG_DONTWAIT,
9812+ &err);
9813+ if (!skb) {
9814+ dev_put(dev);
9815+ return err;
9816+ }
9817+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
9818+
9819+ skb_reset_network_header(skb);
9820+
9821+ MAC_CB(skb)->flags = IEEE80215_FC_TYPE_DATA | MAC_CB_FLAG_ACKREQ;
9822+ MAC_CB(skb)->seq = hw->dsn;
9823+ err = dev_hard_header(skb, dev, ETH_P_IEEE80215, &ro->dst_addr, ro->bound ? &ro->src_addr : NULL, size);
9824+ if (err < 0) {
9825+ kfree_skb(skb);
9826+ dev_put(dev);
9827+ return err;
9828+ }
9829+
9830+ skb_reset_mac_header(skb);
9831+
9832+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
9833+ if (err < 0) {
9834+ kfree_skb(skb);
9835+ dev_put(dev);
9836+ return err;
9837+ }
9838+
9839+ if (size > mtu) {
9840+ pr_debug("size = %u, mtu = %u\n", size, mtu);
9841+ return -EINVAL;
9842+ }
9843+
9844+ skb->dev = dev;
9845+ skb->sk = sk;
9846+ skb->protocol = htons(ETH_P_IEEE80215);
9847+
9848+ err = dev_queue_xmit(skb);
9849+ hw->dsn++;
9850+
9851+ dev_put(dev);
9852+
9853+ if (err)
9854+ return err;
9855+
9856+ return size;
9857+}
9858+
9859+static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
9860+ size_t len, int noblock, int flags, int *addr_len)
9861+{
9862+ size_t copied = 0;
9863+ int err = -EOPNOTSUPP;
9864+ struct sk_buff *skb;
9865+
9866+ skb = skb_recv_datagram(sk, flags, noblock, &err);
9867+ if (!skb)
9868+ goto out;
9869+
9870+ copied = skb->len;
9871+ if (len < copied) {
9872+ msg->msg_flags |= MSG_TRUNC;
9873+ copied = len;
9874+ }
9875+
9876+ // FIXME: skip headers if necessary ?!
9877+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
9878+ if (err)
9879+ goto done;
9880+
9881+ sock_recv_timestamp(msg, sk, skb);
9882+
9883+ if (flags & MSG_TRUNC)
9884+ copied = skb->len;
9885+done:
9886+ skb_free_datagram(sk, skb);
9887+out:
9888+ if (err)
9889+ return err;
9890+ return copied;
9891+}
9892+
9893+static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
9894+{
9895+ if (sock_queue_rcv_skb(sk, skb) < 0) {
9896+ atomic_inc(&sk->sk_drops);
9897+ kfree_skb(skb);
9898+ return NET_RX_DROP;
9899+ }
9900+
9901+ return NET_RX_SUCCESS;
9902+}
9903+
9904+int ieee80215_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
9905+{
9906+ struct sock *sk, *prev = NULL;
9907+ struct hlist_node*node;
9908+ int ret = NET_RX_SUCCESS;
9909+
9910+ /* Data frame processing */
9911+
9912+ read_lock(&dgram_lock);
9913+ sk_for_each(sk, node, &dgram_head) {
9914+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9915+ if (!ro->bound ||
9916+ (ro->src_addr.addr_type == IEEE80215_ADDR_LONG &&
9917+ !memcmp(ro->src_addr.hwaddr, dev->dev_addr, IEEE80215_ADDR_LEN)) ||
9918+ (ro->src_addr.addr_type == IEEE80215_ADDR_SHORT &&
9919+ ieee80215_dev_get_pan_id(dev) == ro->src_addr.pan_id &&
9920+ ieee80215_dev_get_short_addr(dev) == ro->src_addr.short_addr)) {
9921+ if (prev) {
9922+ struct sk_buff *clone;
9923+ clone = skb_clone(skb, GFP_ATOMIC);
9924+ if (clone)
9925+ dgram_rcv_skb(prev, clone);
9926+ }
9927+
9928+ prev = sk;
9929+ }
9930+ }
9931+
9932+ if (prev)
9933+ dgram_rcv_skb(prev, skb);
9934+ else {
9935+ kfree_skb(skb);
9936+ ret = NET_RX_DROP;
9937+ }
9938+ read_unlock(&dgram_lock);
9939+
9940+ return ret;
9941+}
9942+
9943+struct proto ieee80215_dgram_prot = {
9944+ .name = "ZigBEE",
9945+ .owner = THIS_MODULE,
9946+ .obj_size = sizeof(struct dgram_sock),
9947+ .init = dgram_init,
9948+ .close = dgram_close,
9949+ .bind = dgram_bind,
9950+ .sendmsg = dgram_sendmsg,
9951+ .recvmsg = dgram_recvmsg,
9952+ .hash = dgram_hash,
9953+ .unhash = dgram_unhash,
9954+ .connect = dgram_connect,
9955+ .disconnect = dgram_disconnect,
9956+ .ioctl = dgram_ioctl,
9957+};
9958+
9959--
99601.7.4.1
9961
target/linux/xburst/patches-3.0/0032-set-atben-GPIO-to-func_none.patch
1From 24c474c864c5b53c068a3203393e40894a385fb8 Mon Sep 17 00:00:00 2001
2From: Xiangfu Liu <xiangfu@sharism.cc>
3Date: Tue, 1 Nov 2011 21:15:26 +0800
4Subject: [PATCH 32/32] set atben GPIO to func_none
5
6---
7 arch/mips/jz4740/board-qi_lb60.c | 7 +++++++
8 1 files changed, 7 insertions(+), 0 deletions(-)
9
10diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
11index 0bc4caa..67a5fa3 100644
12--- a/arch/mips/jz4740/board-qi_lb60.c
13@@ -446,6 +446,13 @@ static void __init board_gpio_setup(void)
14      * drivers. Everything else is done by the drivers themselves. */
15     jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
16     jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
17+
18+ jz_gpio_set_function(JZ_GPIO_PORTD(8), JZ_GPIO_FUNC_NONE);
19+ jz_gpio_set_function(JZ_GPIO_PORTD(9), JZ_GPIO_FUNC_NONE);
20+ jz_gpio_set_function(JZ_GPIO_PORTD(10), JZ_GPIO_FUNC_NONE);
21+ jz_gpio_set_function(JZ_GPIO_PORTD(11), JZ_GPIO_FUNC_NONE);
22+ jz_gpio_set_function(JZ_GPIO_PORTD(12), JZ_GPIO_FUNC_NONE);
23+ jz_gpio_set_function(JZ_GPIO_PORTD(13), JZ_GPIO_FUNC_NONE);
24 }
25
26 static int __init qi_lb60_init_platform_devices(void)
27--
281.7.4.1
29

Archive Download the corresponding diff file



interactive