| Masakazu Mokuno | 09dde54 | 2008-02-07 19:58:57 +0900 | [diff] [blame] | 1 | /* | 
|  | 2 | *  PS3 gelic network driver. | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 
|  | 5 | * Copyright 2007 Sony Corporation | 
|  | 6 | * | 
|  | 7 | * This program is free software; you can redistribute it and/or modify | 
|  | 8 | * it under the terms of the GNU General Public License as published by | 
|  | 9 | * the Free Software Foundation version 2. | 
|  | 10 | * | 
|  | 11 | * This program is distributed in the hope that it will be useful, | 
|  | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 14 | * GNU General Public License for more details. | 
|  | 15 | * | 
|  | 16 | * You should have received a copy of the GNU General Public License | 
|  | 17 | * along with this program; if not, write to the Free Software | 
|  | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 19 | */ | 
|  | 20 | #ifndef _GELIC_WIRELESS_H | 
|  | 21 | #define _GELIC_WIRELESS_H | 
|  | 22 |  | 
|  | 23 | #include <linux/wireless.h> | 
|  | 24 | #include <net/iw_handler.h> | 
|  | 25 |  | 
|  | 26 |  | 
|  | 27 | /* return value from  GELIC_LV1_GET_WLAN_EVENT netcontrol */ | 
|  | 28 | enum gelic_lv1_wl_event { | 
|  | 29 | GELIC_LV1_WL_EVENT_DEVICE_READY   = 0x01, /* Eurus ready */ | 
|  | 30 | GELIC_LV1_WL_EVENT_SCAN_COMPLETED = 0x02, /* Scan has completed */ | 
|  | 31 | GELIC_LV1_WL_EVENT_DEAUTH         = 0x04, /* Deauthed by the AP */ | 
|  | 32 | GELIC_LV1_WL_EVENT_BEACON_LOST    = 0x08, /* Beacon lost detected */ | 
|  | 33 | GELIC_LV1_WL_EVENT_CONNECTED      = 0x10, /* Connected to AP */ | 
|  | 34 | GELIC_LV1_WL_EVENT_WPA_CONNECTED  = 0x20, /* WPA connection */ | 
|  | 35 | GELIC_LV1_WL_EVENT_WPA_ERROR      = 0x40, /* MIC error */ | 
|  | 36 | }; | 
|  | 37 |  | 
|  | 38 | /* arguments for GELIC_LV1_POST_WLAN_COMMAND netcontrol */ | 
|  | 39 | enum gelic_eurus_command { | 
|  | 40 | GELIC_EURUS_CMD_ASSOC		=  1, /* association start */ | 
|  | 41 | GELIC_EURUS_CMD_DISASSOC	=  2, /* disassociate      */ | 
|  | 42 | GELIC_EURUS_CMD_START_SCAN	=  3, /* scan start        */ | 
|  | 43 | GELIC_EURUS_CMD_GET_SCAN	=  4, /* get scan result   */ | 
|  | 44 | GELIC_EURUS_CMD_SET_COMMON_CFG	=  5, /* set common config */ | 
|  | 45 | GELIC_EURUS_CMD_GET_COMMON_CFG	=  6, /* set common config */ | 
|  | 46 | GELIC_EURUS_CMD_SET_WEP_CFG	=  7, /* set WEP config    */ | 
|  | 47 | GELIC_EURUS_CMD_GET_WEP_CFG	=  8, /* get WEP config    */ | 
|  | 48 | GELIC_EURUS_CMD_SET_WPA_CFG	=  9, /* set WPA config    */ | 
|  | 49 | GELIC_EURUS_CMD_GET_WPA_CFG	= 10, /* get WPA config    */ | 
|  | 50 | GELIC_EURUS_CMD_GET_RSSI_CFG	= 11, /* get RSSI info.    */ | 
|  | 51 | GELIC_EURUS_CMD_MAX_INDEX | 
|  | 52 | }; | 
|  | 53 |  | 
|  | 54 | /* for GELIC_EURUS_CMD_COMMON_CFG */ | 
|  | 55 | enum gelic_eurus_bss_type { | 
|  | 56 | GELIC_EURUS_BSS_INFRA = 0, | 
|  | 57 | GELIC_EURUS_BSS_ADHOC = 1, /* not supported */ | 
|  | 58 | }; | 
|  | 59 |  | 
|  | 60 | enum gelic_eurus_auth_method { | 
|  | 61 | GELIC_EURUS_AUTH_OPEN = 0, /* FIXME: WLAN_AUTH_OPEN */ | 
|  | 62 | GELIC_EURUS_AUTH_SHARED = 1, /* not supported */ | 
|  | 63 | }; | 
|  | 64 |  | 
|  | 65 | enum gelic_eurus_opmode { | 
|  | 66 | GELIC_EURUS_OPMODE_11BG = 0, /* 802.11b/g */ | 
|  | 67 | GELIC_EURUS_OPMODE_11B = 1, /* 802.11b only */ | 
|  | 68 | GELIC_EURUS_OPMODE_11G = 2, /* 802.11g only */ | 
|  | 69 | }; | 
|  | 70 |  | 
|  | 71 | struct gelic_eurus_common_cfg { | 
|  | 72 | /* all fields are big endian */ | 
|  | 73 | u16 scan_index; | 
|  | 74 | u16 bss_type;    /* infra or adhoc */ | 
|  | 75 | u16 auth_method; /* shared key or open */ | 
|  | 76 | u16 op_mode; /* B/G */ | 
|  | 77 | } __attribute__((packed)); | 
|  | 78 |  | 
|  | 79 |  | 
|  | 80 | /* for GELIC_EURUS_CMD_WEP_CFG */ | 
|  | 81 | enum gelic_eurus_wep_security { | 
|  | 82 | GELIC_EURUS_WEP_SEC_NONE	= 0, | 
|  | 83 | GELIC_EURUS_WEP_SEC_40BIT	= 1, | 
|  | 84 | GELIC_EURUS_WEP_SEC_104BIT	= 2, | 
|  | 85 | }; | 
|  | 86 |  | 
|  | 87 | struct gelic_eurus_wep_cfg { | 
|  | 88 | /* all fields are big endian */ | 
|  | 89 | u16 security; | 
|  | 90 | u8 key[4][16]; | 
|  | 91 | } __attribute__((packed)); | 
|  | 92 |  | 
|  | 93 | /* for GELIC_EURUS_CMD_WPA_CFG */ | 
|  | 94 | enum gelic_eurus_wpa_security { | 
|  | 95 | GELIC_EURUS_WPA_SEC_NONE		= 0x0000, | 
|  | 96 | /* group=TKIP, pairwise=TKIP */ | 
|  | 97 | GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP	= 0x0001, | 
|  | 98 | /* group=AES, pairwise=AES */ | 
|  | 99 | GELIC_EURUS_WPA_SEC_WPA_AES_AES		= 0x0002, | 
|  | 100 | /* group=TKIP, pairwise=TKIP */ | 
|  | 101 | GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP	= 0x0004, | 
|  | 102 | /* group=AES, pairwise=AES */ | 
|  | 103 | GELIC_EURUS_WPA_SEC_WPA2_AES_AES	= 0x0008, | 
|  | 104 | /* group=TKIP, pairwise=AES */ | 
|  | 105 | GELIC_EURUS_WPA_SEC_WPA_TKIP_AES	= 0x0010, | 
|  | 106 | /* group=TKIP, pairwise=AES */ | 
|  | 107 | GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES	= 0x0020, | 
|  | 108 | }; | 
|  | 109 |  | 
|  | 110 | enum gelic_eurus_wpa_psk_type { | 
|  | 111 | GELIC_EURUS_WPA_PSK_PASSPHRASE	= 0, /* passphrase string   */ | 
|  | 112 | GELIC_EURUS_WPA_PSK_BIN		= 1, /* 32 bytes binary key */ | 
|  | 113 | }; | 
|  | 114 |  | 
|  | 115 | #define GELIC_WL_EURUS_PSK_MAX_LEN	64 | 
|  | 116 | #define WPA_PSK_LEN			32 /* WPA spec says 256bit */ | 
|  | 117 |  | 
|  | 118 | struct gelic_eurus_wpa_cfg { | 
|  | 119 | /* all fields are big endian */ | 
|  | 120 | u16 security; | 
|  | 121 | u16 psk_type; /* psk key encoding type */ | 
|  | 122 | u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; /* psk key; hex or passphrase */ | 
|  | 123 | } __attribute__((packed)); | 
|  | 124 |  | 
|  | 125 | /* for GELIC_EURUS_CMD_{START,GET}_SCAN */ | 
|  | 126 | enum gelic_eurus_scan_capability { | 
|  | 127 | GELIC_EURUS_SCAN_CAP_ADHOC	= 0x0000, | 
|  | 128 | GELIC_EURUS_SCAN_CAP_INFRA	= 0x0001, | 
|  | 129 | GELIC_EURUS_SCAN_CAP_MASK	= 0x0001, | 
|  | 130 | }; | 
|  | 131 |  | 
|  | 132 | enum gelic_eurus_scan_sec_type { | 
|  | 133 | GELIC_EURUS_SCAN_SEC_NONE	= 0x0000, | 
|  | 134 | GELIC_EURUS_SCAN_SEC_WEP	= 0x0100, | 
|  | 135 | GELIC_EURUS_SCAN_SEC_WPA	= 0x0200, | 
|  | 136 | GELIC_EURUS_SCAN_SEC_WPA2	= 0x0400, | 
|  | 137 | GELIC_EURUS_SCAN_SEC_MASK	= 0x0f00, | 
|  | 138 | }; | 
|  | 139 |  | 
|  | 140 | enum gelic_eurus_scan_sec_wep_type { | 
|  | 141 | GELIC_EURUS_SCAN_SEC_WEP_UNKNOWN	= 0x0000, | 
|  | 142 | GELIC_EURUS_SCAN_SEC_WEP_40		= 0x0001, | 
|  | 143 | GELIC_EURUS_SCAN_SEC_WEP_104		= 0x0002, | 
|  | 144 | GELIC_EURUS_SCAN_SEC_WEP_MASK		= 0x0003, | 
|  | 145 | }; | 
|  | 146 |  | 
|  | 147 | enum gelic_eurus_scan_sec_wpa_type { | 
|  | 148 | GELIC_EURUS_SCAN_SEC_WPA_UNKNOWN	= 0x0000, | 
|  | 149 | GELIC_EURUS_SCAN_SEC_WPA_TKIP		= 0x0001, | 
|  | 150 | GELIC_EURUS_SCAN_SEC_WPA_AES		= 0x0002, | 
|  | 151 | GELIC_EURUS_SCAN_SEC_WPA_MASK		= 0x0003, | 
|  | 152 | }; | 
|  | 153 |  | 
|  | 154 | /* | 
|  | 155 | * hw BSS information structure returned from GELIC_EURUS_CMD_GET_SCAN | 
|  | 156 | */ | 
|  | 157 | struct gelic_eurus_scan_info { | 
|  | 158 | /* all fields are big endian */ | 
|  | 159 | __be16 size; | 
|  | 160 | __be16 rssi; /* percentage */ | 
|  | 161 | __be16 channel; /* channel number */ | 
|  | 162 | __be16 beacon_period; /* FIXME: in msec unit */ | 
|  | 163 | __be16 capability; | 
|  | 164 | __be16 security; | 
|  | 165 | u8  bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */ | 
|  | 166 | u8  essid[32]; /* IW_ESSID_MAX_SIZE */ | 
| Johannes Berg | 2c706002 | 2008-10-30 22:09:54 +0100 | [diff] [blame] | 167 | u8  rate[16]; /* first 12 are valid */ | 
|  | 168 | u8  ext_rate[16]; /* first 16 are valid */ | 
| Masakazu Mokuno | 09dde54 | 2008-02-07 19:58:57 +0900 | [diff] [blame] | 169 | __be32 reserved1; | 
|  | 170 | __be32 reserved2; | 
|  | 171 | __be32 reserved3; | 
|  | 172 | __be32 reserved4; | 
|  | 173 | u8 elements[0]; /* ie */ | 
|  | 174 | } __attribute__ ((packed)); | 
|  | 175 |  | 
|  | 176 | /* the hypervisor returns bbs up to 16 */ | 
|  | 177 | #define GELIC_EURUS_MAX_SCAN  (16) | 
|  | 178 | struct gelic_wl_scan_info { | 
|  | 179 | struct list_head list; | 
|  | 180 | struct gelic_eurus_scan_info *hwinfo; | 
|  | 181 |  | 
|  | 182 | int valid; /* set 1 if this entry was in latest scanned list | 
|  | 183 | * from Eurus */ | 
|  | 184 | unsigned int eurus_index; /* index in the Eurus list */ | 
|  | 185 | unsigned long last_scanned; /* acquired time */ | 
|  | 186 |  | 
|  | 187 | unsigned int rate_len; | 
|  | 188 | unsigned int rate_ext_len; | 
|  | 189 | unsigned int essid_len; | 
|  | 190 | }; | 
|  | 191 |  | 
|  | 192 | /* for GELIC_EURUS_CMD_GET_RSSI */ | 
|  | 193 | struct gelic_eurus_rssi_info { | 
|  | 194 | /* big endian */ | 
|  | 195 | __be16 rssi; | 
|  | 196 | } __attribute__ ((packed)); | 
|  | 197 |  | 
|  | 198 |  | 
|  | 199 | /* for 'stat' member of gelic_wl_info */ | 
|  | 200 | enum gelic_wl_info_status_bit { | 
|  | 201 | GELIC_WL_STAT_CONFIGURED, | 
|  | 202 | GELIC_WL_STAT_CH_INFO,   /* ch info aquired */ | 
|  | 203 | GELIC_WL_STAT_ESSID_SET, /* ESSID specified by userspace */ | 
|  | 204 | GELIC_WL_STAT_BSSID_SET, /* BSSID specified by userspace */ | 
|  | 205 | GELIC_WL_STAT_WPA_PSK_SET, /* PMK specified by userspace */ | 
|  | 206 | GELIC_WL_STAT_WPA_LEVEL_SET, /* WEP or WPA[2] selected */ | 
|  | 207 | }; | 
|  | 208 |  | 
|  | 209 | /* for 'scan_stat' member of gelic_wl_info */ | 
|  | 210 | enum gelic_wl_scan_state { | 
|  | 211 | /* just initialized or get last scan result failed */ | 
|  | 212 | GELIC_WL_SCAN_STAT_INIT, | 
|  | 213 | /* scan request issued, accepted or chip is scanning */ | 
|  | 214 | GELIC_WL_SCAN_STAT_SCANNING, | 
|  | 215 | /* scan results retrieved */ | 
|  | 216 | GELIC_WL_SCAN_STAT_GOT_LIST, | 
|  | 217 | }; | 
|  | 218 |  | 
|  | 219 | /* for 'cipher_method' */ | 
|  | 220 | enum gelic_wl_cipher_method { | 
|  | 221 | GELIC_WL_CIPHER_NONE, | 
|  | 222 | GELIC_WL_CIPHER_WEP, | 
|  | 223 | GELIC_WL_CIPHER_TKIP, | 
|  | 224 | GELIC_WL_CIPHER_AES, | 
|  | 225 | }; | 
|  | 226 |  | 
|  | 227 | /* for 'wpa_level' */ | 
|  | 228 | enum gelic_wl_wpa_level { | 
|  | 229 | GELIC_WL_WPA_LEVEL_NONE, | 
|  | 230 | GELIC_WL_WPA_LEVEL_WPA, | 
|  | 231 | GELIC_WL_WPA_LEVEL_WPA2, | 
|  | 232 | }; | 
|  | 233 |  | 
|  | 234 | /* for 'assoc_stat' */ | 
|  | 235 | enum gelic_wl_assoc_state { | 
|  | 236 | GELIC_WL_ASSOC_STAT_DISCONN, | 
|  | 237 | GELIC_WL_ASSOC_STAT_ASSOCIATING, | 
|  | 238 | GELIC_WL_ASSOC_STAT_ASSOCIATED, | 
|  | 239 | }; | 
|  | 240 | /* part of private data alloc_etherdev() allocated */ | 
|  | 241 | #define GELIC_WEP_KEYS 4 | 
|  | 242 | struct gelic_wl_info { | 
|  | 243 | /* bss list */ | 
| Daniel Walker | 706ddd6 | 2008-05-22 00:00:01 -0700 | [diff] [blame] | 244 | struct mutex scan_lock; | 
| Masakazu Mokuno | 09dde54 | 2008-02-07 19:58:57 +0900 | [diff] [blame] | 245 | struct list_head network_list; | 
|  | 246 | struct list_head network_free_list; | 
|  | 247 | struct gelic_wl_scan_info *networks; | 
|  | 248 |  | 
|  | 249 | unsigned long scan_age; /* last scanned time */ | 
|  | 250 | enum gelic_wl_scan_state scan_stat; | 
|  | 251 | struct completion scan_done; | 
|  | 252 |  | 
|  | 253 | /* eurus command queue */ | 
|  | 254 | struct workqueue_struct *eurus_cmd_queue; | 
|  | 255 | struct completion cmd_done_intr; | 
|  | 256 |  | 
|  | 257 | /* eurus event handling */ | 
|  | 258 | struct workqueue_struct *event_queue; | 
|  | 259 | struct delayed_work event_work; | 
|  | 260 |  | 
|  | 261 | /* wl status bits */ | 
|  | 262 | unsigned long stat; | 
|  | 263 | enum gelic_eurus_auth_method auth_method; /* open/shared */ | 
|  | 264 | enum gelic_wl_cipher_method group_cipher_method; | 
|  | 265 | enum gelic_wl_cipher_method pairwise_cipher_method; | 
|  | 266 | enum gelic_wl_wpa_level wpa_level; /* wpa/wpa2 */ | 
|  | 267 |  | 
|  | 268 | /* association handling */ | 
| Daniel Walker | bb2d67a | 2008-05-22 00:00:02 -0700 | [diff] [blame] | 269 | struct mutex assoc_stat_lock; | 
| Masakazu Mokuno | 09dde54 | 2008-02-07 19:58:57 +0900 | [diff] [blame] | 270 | struct delayed_work assoc_work; | 
|  | 271 | enum gelic_wl_assoc_state assoc_stat; | 
|  | 272 | struct completion assoc_done; | 
|  | 273 |  | 
|  | 274 | spinlock_t lock; | 
|  | 275 | u16 ch_info; /* available channels. bit0 = ch1 */ | 
|  | 276 | /* WEP keys */ | 
|  | 277 | u8 key[GELIC_WEP_KEYS][IW_ENCODING_TOKEN_MAX]; | 
|  | 278 | unsigned long key_enabled; | 
|  | 279 | unsigned int key_len[GELIC_WEP_KEYS]; | 
|  | 280 | unsigned int current_key; | 
|  | 281 | /* WWPA PSK */ | 
|  | 282 | u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; | 
|  | 283 | enum gelic_eurus_wpa_psk_type psk_type; | 
|  | 284 | unsigned int psk_len; | 
|  | 285 |  | 
|  | 286 | u8 essid[IW_ESSID_MAX_SIZE]; | 
|  | 287 | u8 bssid[ETH_ALEN]; /* userland requested */ | 
|  | 288 | u8 active_bssid[ETH_ALEN]; /* associated bssid */ | 
|  | 289 | unsigned int essid_len; | 
|  | 290 |  | 
| Masakazu Mokuno | 09dde54 | 2008-02-07 19:58:57 +0900 | [diff] [blame] | 291 | struct iw_public_data wireless_data; | 
|  | 292 | struct iw_statistics iwstat; | 
|  | 293 | }; | 
|  | 294 |  | 
|  | 295 | #define GELIC_WL_BSS_MAX_ENT 32 | 
|  | 296 | #define GELIC_WL_ASSOC_RETRY 50 | 
|  | 297 | static inline struct gelic_port *wl_port(struct gelic_wl_info *wl) | 
|  | 298 | { | 
|  | 299 | return container_of((void *)wl, struct gelic_port, priv); | 
|  | 300 | } | 
|  | 301 | static inline struct gelic_wl_info *port_wl(struct gelic_port *port) | 
|  | 302 | { | 
|  | 303 | return port_priv(port); | 
|  | 304 | } | 
|  | 305 |  | 
|  | 306 | struct gelic_eurus_cmd { | 
|  | 307 | struct work_struct work; | 
|  | 308 | struct gelic_wl_info *wl; | 
|  | 309 | unsigned int cmd; /* command code */ | 
|  | 310 | u64 tag; | 
|  | 311 | u64 size; | 
|  | 312 | void *buffer; | 
|  | 313 | unsigned int buf_size; | 
|  | 314 | struct completion done; | 
|  | 315 | int status; | 
|  | 316 | u64 cmd_status; | 
|  | 317 | }; | 
|  | 318 |  | 
|  | 319 | /* private ioctls to pass PSK */ | 
|  | 320 | #define GELIC_WL_PRIV_SET_PSK		(SIOCIWFIRSTPRIV + 0) | 
|  | 321 | #define GELIC_WL_PRIV_GET_PSK		(SIOCIWFIRSTPRIV + 1) | 
|  | 322 |  | 
|  | 323 | extern int gelic_wl_driver_probe(struct gelic_card *card); | 
|  | 324 | extern int gelic_wl_driver_remove(struct gelic_card *card); | 
|  | 325 | extern void gelic_wl_interrupt(struct net_device *netdev, u64 status); | 
|  | 326 | #endif /* _GELIC_WIRELESS_H */ |