drivers/net/wireless/ks7010/ks7010_sdio.c |
| 1 | /* |
| 2 | * Driver for KeyStream, KS7010 based SDIO cards. |
| 3 | * |
| 4 | * ks7010_sdio.c |
| 5 | * $Id: ks7010_sdio.c 996 2009-09-14 02:54:21Z sekine $ |
| 6 | * |
| 7 | * Copyright (C) 2006-2008 KeyStream Corp. |
| 8 | * Copyright (C) 2009 Renesas Technology Corp. |
| 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it undr the terms of the GNU General Public License version 2 as |
| 12 | * published by the Free Sotware Foundation. |
| 13 | */ |
| 14 | |
| 15 | #include <linux/workqueue.h> |
| 16 | #include <asm/atomic.h> |
| 17 | #include <linux/mmc/card.h> |
| 18 | #include <linux/mmc/sdio_func.h> |
| 19 | |
| 20 | #include "ks_wlan.h" |
| 21 | #include "ks_wlan_ioctl.h" |
| 22 | #include "ks_debug.h" |
| 23 | #include "ks_hostif.h" |
| 24 | |
| 25 | #include "ks7010_sdio.h" |
| 26 | |
| 27 | #define KS7010_FUNC_NUM 1 |
| 28 | #define KS7010_IO_BLOCK_SIZE 512 |
| 29 | #define KS7010_MAX_CLOCK 25000000 |
| 30 | |
| 31 | static int reg_net = 0; |
| 32 | |
| 33 | static const struct sdio_device_id if_sdio_ids[] = { |
| 34 | { SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_A, SDIO_DEVICE_ID_KS_7010) }, |
| 35 | { SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_B, SDIO_DEVICE_ID_KS_7010) }, |
| 36 | { /* all zero */ } |
| 37 | }; |
| 38 | |
| 39 | struct ks_sdio_model { |
| 40 | int model; |
| 41 | const char *firmware; |
| 42 | }; |
| 43 | |
| 44 | static struct ks_sdio_model ks_sdio_models[] = { |
| 45 | { |
| 46 | /* ks7010 */ |
| 47 | .model = 0x10, |
| 48 | .firmware = "ks7010sd.rom", |
| 49 | }, |
| 50 | }; |
| 51 | |
| 52 | static int ks7910_sdio_probe(struct sdio_func *function, const struct sdio_device_id *device); |
| 53 | static void ks7910_sdio_remove(struct sdio_func *function); |
| 54 | static void ks7010_rw_function(struct work_struct *work); |
| 55 | static int ks7010_sdio_read( ks_wlan_private *priv, unsigned long address, |
| 56 | unsigned char *buffer, unsigned long length ); |
| 57 | static int ks7010_sdio_write( ks_wlan_private *priv, unsigned long address, |
| 58 | unsigned char *buffer, unsigned long length ); |
| 59 | #ifdef NO_FIRMWARE_CLASS |
| 60 | static char *romfile = ROM_FILE; |
| 61 | module_param(romfile, charp, S_IRUGO); |
| 62 | #endif |
| 63 | /* macro */ |
| 64 | |
| 65 | #define inc_txqhead(priv) \ |
| 66 | ( priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE ) |
| 67 | #define inc_txqtail(priv) \ |
| 68 | ( priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE ) |
| 69 | #define cnt_txqbody(priv) \ |
| 70 | (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE ) |
| 71 | |
| 72 | #define inc_rxqhead(priv) \ |
| 73 | ( priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE ) |
| 74 | #define inc_rxqtail(priv) \ |
| 75 | ( priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE ) |
| 76 | #define cnt_rxqbody(priv) \ |
| 77 | (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE ) |
| 78 | |
| 79 | void ks_wlan_hw_sleep_doze_request(ks_wlan_private *priv) |
| 80 | { |
| 81 | unsigned char rw_data; |
| 82 | int retval; |
| 83 | |
| 84 | DPRINTK(4, "\n"); |
| 85 | |
| 86 | /* clear request */ |
| 87 | atomic_set(&priv->sleepstatus.doze_request,0); |
| 88 | |
| 89 | if( atomic_read(&priv->sleepstatus.status) == 0){ |
| 90 | rw_data = GCR_B_DOZE; |
| 91 | retval = ks7010_sdio_write(priv, GCR_B, &rw_data, sizeof(rw_data)); |
| 92 | if(retval){ |
| 93 | DPRINTK(1, " error : GCR_B=%02X\n", rw_data); |
| 94 | goto out; |
| 95 | } |
| 96 | DPRINTK(4, "PMG SET!! : GCR_B=%02X\n", rw_data); |
| 97 | DPRINTK(3,"sleep_mode=SLP_SLEEP\n"); |
| 98 | atomic_set(&priv->sleepstatus.status, 1); |
| 99 | priv->last_doze = jiffies; |
| 100 | } |
| 101 | else{ |
| 102 | DPRINTK(1,"sleep_mode=%d\n",priv->sleep_mode); |
| 103 | } |
| 104 | |
| 105 | out: |
| 106 | priv->sleep_mode = atomic_read(&priv->sleepstatus.status); |
| 107 | return; |
| 108 | } |
| 109 | |
| 110 | void ks_wlan_hw_sleep_wakeup_request(ks_wlan_private *priv) |
| 111 | { |
| 112 | unsigned char rw_data; |
| 113 | int retval; |
| 114 | |
| 115 | DPRINTK(4, "\n"); |
| 116 | |
| 117 | /* clear request */ |
| 118 | atomic_set(&priv->sleepstatus.wakeup_request,0); |
| 119 | |
| 120 | if( atomic_read(&priv->sleepstatus.status) == 1){ |
| 121 | rw_data = WAKEUP_REQ; |
| 122 | retval = ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data)); |
| 123 | if(retval){ |
| 124 | DPRINTK(1, " error : WAKEUP=%02X\n", rw_data); |
| 125 | goto out; |
| 126 | } |
| 127 | DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data); |
| 128 | atomic_set(&priv->sleepstatus.status, 0); |
| 129 | priv->last_wakeup = jiffies; |
| 130 | ++priv->wakeup_count; |
| 131 | } |
| 132 | else{ |
| 133 | DPRINTK(1,"sleep_mode=%d\n",priv->sleep_mode); |
| 134 | } |
| 135 | |
| 136 | out: |
| 137 | priv->sleep_mode = atomic_read(&priv->sleepstatus.status); |
| 138 | return; |
| 139 | } |
| 140 | |
| 141 | |
| 142 | void ks_wlan_hw_wakeup_request(ks_wlan_private *priv) |
| 143 | { |
| 144 | unsigned char rw_data; |
| 145 | int retval; |
| 146 | |
| 147 | DPRINTK(4, "\n"); |
| 148 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE){ |
| 149 | rw_data = WAKEUP_REQ; |
| 150 | retval = ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data)); |
| 151 | if(retval){ |
| 152 | DPRINTK(1, " error : WAKEUP=%02X\n", rw_data); |
| 153 | } |
| 154 | DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data); |
| 155 | priv->last_wakeup = jiffies; |
| 156 | ++priv->wakeup_count; |
| 157 | } |
| 158 | else{ |
| 159 | DPRINTK(1,"psstatus=%d\n",atomic_read(&priv->psstatus.status)); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | int _ks_wlan_hw_power_save(ks_wlan_private *priv) |
| 164 | { |
| 165 | int rc=0; |
| 166 | unsigned char rw_data; |
| 167 | int retval; |
| 168 | |
| 169 | if(priv->reg.powermgt == POWMGT_ACTIVE_MODE) |
| 170 | return rc; |
| 171 | |
| 172 | if(priv->reg.operation_mode == MODE_INFRASTRUCTURE && |
| 173 | (priv->connect_status & CONNECT_STATUS_MASK)== CONNECT_STATUS){ |
| 174 | |
| 175 | //DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status)); |
| 176 | if (priv->dev_state == DEVICE_STATE_SLEEP) { |
| 177 | switch(atomic_read(&priv->psstatus.status)){ |
| 178 | case PS_SNOOZE: /* 4 */ |
| 179 | break; |
| 180 | default: |
| 181 | DPRINTK(5,"\n\ |
| 182 | psstatus.status=%d\n\ |
| 183 | psstatus.confirm_wait=%d\n\ |
| 184 | psstatus.snooze_guard=%d\n\ |
| 185 | cnt_txqbody=%d\n", |
| 186 | atomic_read(&priv->psstatus.status), |
| 187 | atomic_read(&priv->psstatus.confirm_wait), |
| 188 | atomic_read(&priv->psstatus.snooze_guard), |
| 189 | cnt_txqbody(priv)); |
| 190 | |
| 191 | if(!atomic_read(&priv->psstatus.confirm_wait)&& |
| 192 | !atomic_read(&priv->psstatus.snooze_guard)&& |
| 193 | !cnt_txqbody(priv)){ |
| 194 | retval = ks7010_sdio_read(priv, INT_PENDING, &rw_data, sizeof(rw_data)); |
| 195 | if(retval){ |
| 196 | DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data); |
| 197 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 198 | break; |
| 199 | } |
| 200 | if(!rw_data){ |
| 201 | rw_data = GCR_B_DOZE; |
| 202 | retval = ks7010_sdio_write(priv, GCR_B, &rw_data, sizeof(rw_data)); |
| 203 | if(retval){ |
| 204 | DPRINTK(1, " error : GCR_B=%02X\n", rw_data); |
| 205 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 206 | break; |
| 207 | } |
| 208 | DPRINTK(4, "PMG SET!! : GCR_B=%02X\n", rw_data); |
| 209 | atomic_set(&priv->psstatus.status, PS_SNOOZE); |
| 210 | DPRINTK(3,"psstatus.status=PS_SNOOZE\n"); |
| 211 | } |
| 212 | else{ |
| 213 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 214 | } |
| 215 | } |
| 216 | else{ |
| 217 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 0); |
| 218 | } |
| 219 | break; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | } |
| 224 | |
| 225 | return rc; |
| 226 | } |
| 227 | |
| 228 | int ks_wlan_hw_power_save(ks_wlan_private *priv) |
| 229 | { |
| 230 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 231 | return 0; |
| 232 | } |
| 233 | |
| 234 | static int ks7010_sdio_read(ks_wlan_private *priv, unsigned long address, |
| 235 | unsigned char *buffer, unsigned long length) |
| 236 | { |
| 237 | int rc = -1; |
| 238 | struct ks_sdio_card *card; |
| 239 | |
| 240 | card = priv->ks_wlan_hw.sdio_card; |
| 241 | |
| 242 | if(length == 1){ /* CMD52 */ |
| 243 | *buffer = sdio_readb(card->func, (unsigned int) address, &rc); |
| 244 | } /* CMD53 */ |
| 245 | else{ /* CMD53 multi-block transfer */ |
| 246 | rc = sdio_memcpy_fromio(card->func, buffer, (unsigned int) address, (int) length); |
| 247 | } |
| 248 | if(rc != 0){ |
| 249 | printk("sdio error erorr=%d size=%ld\n",rc, length); |
| 250 | ++priv->sdio_error_count; |
| 251 | }else{ |
| 252 | priv->sdio_error_count=0; |
| 253 | } |
| 254 | |
| 255 | return rc; |
| 256 | } |
| 257 | |
| 258 | static int ks7010_sdio_write(ks_wlan_private *priv, unsigned long address, |
| 259 | unsigned char *buffer, unsigned long length) |
| 260 | { |
| 261 | int rc = -1; |
| 262 | struct ks_sdio_card *card; |
| 263 | |
| 264 | card = priv->ks_wlan_hw.sdio_card; |
| 265 | |
| 266 | if(length == 1){ /* CMD52 */ |
| 267 | sdio_writeb(card->func, *buffer, (unsigned int) address, &rc); |
| 268 | } |
| 269 | else{ /* CMD53 */ |
| 270 | rc = sdio_memcpy_toio(card->func, (unsigned int) address, buffer, length); |
| 271 | } |
| 272 | if(rc != 0){ |
| 273 | printk("sdio error erorr=%d size=%ld\n",rc, length); |
| 274 | ++priv->sdio_error_count; |
| 275 | }else{ |
| 276 | priv->sdio_error_count=0; |
| 277 | } |
| 278 | |
| 279 | return rc; |
| 280 | } |
| 281 | |
| 282 | static int enqueue_txdev(ks_wlan_private *priv, unsigned char *p, unsigned long size, |
| 283 | void (*complete_handler)(void *arg1, void *arg2), |
| 284 | void *arg1, void *arg2 ) |
| 285 | { |
| 286 | struct tx_device_buffer *sp; |
| 287 | |
| 288 | if (priv->dev_state < DEVICE_STATE_BOOT) { |
| 289 | kfree(p); |
| 290 | if (complete_handler != NULL) |
| 291 | (*complete_handler)(arg1, arg2); |
| 292 | return 1; |
| 293 | } |
| 294 | |
| 295 | if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) { |
| 296 | /* in case of buffer overflow */ |
| 297 | DPRINTK(1,"tx buffer overflow\n"); |
| 298 | kfree(p); |
| 299 | if (complete_handler != NULL) |
| 300 | (*complete_handler)(arg1, arg2); |
| 301 | return 1; |
| 302 | } |
| 303 | |
| 304 | sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qtail]; |
| 305 | sp->sendp = p; |
| 306 | sp->size = size; |
| 307 | sp->complete_handler = complete_handler; |
| 308 | sp->arg1 = arg1; |
| 309 | sp->arg2 = arg2; |
| 310 | inc_txqtail(priv); |
| 311 | |
| 312 | return 0; |
| 313 | } |
| 314 | |
| 315 | /* write data */ |
| 316 | static int write_to_device(ks_wlan_private *priv, unsigned char *buffer, unsigned long size ) |
| 317 | { |
| 318 | int rc,retval; |
| 319 | unsigned char rw_data; |
| 320 | struct hostif_hdr *hdr; |
| 321 | hdr = (struct hostif_hdr *)buffer; |
| 322 | rc=0; |
| 323 | |
| 324 | DPRINTK(4,"size=%d\n", hdr->size); |
| 325 | if(hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event){ |
| 326 | DPRINTK(1,"unknown event=%04X\n",hdr->event); |
| 327 | return 0; |
| 328 | } |
| 329 | |
| 330 | retval = ks7010_sdio_write(priv, DATA_WINDOW, buffer, size); |
| 331 | if(retval){ |
| 332 | DPRINTK(1, " write error : retval=%d\n", retval); |
| 333 | return -4; |
| 334 | } |
| 335 | |
| 336 | rw_data = WRITE_STATUS_BUSY; |
| 337 | retval = ks7010_sdio_write(priv, WRITE_STATUS, &rw_data, sizeof(rw_data)); |
| 338 | if(retval){ |
| 339 | DPRINTK(1, " error : WRITE_STATUS=%02X\n", rw_data); |
| 340 | return -3; |
| 341 | } |
| 342 | |
| 343 | return 0; |
| 344 | } |
| 345 | |
| 346 | static void tx_device_task(void *dev) |
| 347 | { |
| 348 | ks_wlan_private *priv = (ks_wlan_private *)dev; |
| 349 | struct tx_device_buffer *sp; |
| 350 | int rc = 0; |
| 351 | |
| 352 | DPRINTK(4, "\n"); |
| 353 | if(cnt_txqbody(priv)>0 && atomic_read(&priv->psstatus.status) != PS_SNOOZE){ |
| 354 | sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead]; |
| 355 | if(priv->dev_state >= DEVICE_STATE_BOOT){ |
| 356 | rc = write_to_device(priv, sp->sendp, sp->size); |
| 357 | if(rc){ |
| 358 | DPRINTK(1, "write_to_device error !!(%d)\n", rc); |
| 359 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 360 | return; |
| 361 | } |
| 362 | |
| 363 | } |
| 364 | kfree(sp->sendp); /* allocated memory free */ |
| 365 | if(sp->complete_handler != NULL) /* TX Complete */ |
| 366 | (*sp->complete_handler)(sp->arg1, sp->arg2); |
| 367 | inc_txqhead(priv); |
| 368 | |
| 369 | if(cnt_txqbody(priv)>0){ |
| 370 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 0); |
| 371 | } |
| 372 | } |
| 373 | return; |
| 374 | } |
| 375 | |
| 376 | int ks_wlan_hw_tx( ks_wlan_private *priv, void *p, unsigned long size, |
| 377 | void (*complete_handler)(void *arg1, void *arg2), |
| 378 | void *arg1, void *arg2 ) |
| 379 | { |
| 380 | int result=0; |
| 381 | struct hostif_hdr *hdr; |
| 382 | hdr = (struct hostif_hdr *)p; |
| 383 | |
| 384 | if(hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event){ |
| 385 | DPRINTK(1,"unknown event=%04X\n",hdr->event); |
| 386 | return 0; |
| 387 | } |
| 388 | |
| 389 | /* add event to hostt buffer */ |
| 390 | priv->hostt.buff[priv->hostt.qtail] = hdr->event; |
| 391 | priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE; |
| 392 | |
| 393 | DPRINTK(4, "event=%04X\n",hdr->event); |
| 394 | spin_lock(&priv->tx_dev.tx_dev_lock); |
| 395 | result = enqueue_txdev(priv, p, size, complete_handler, arg1, arg2); |
| 396 | spin_unlock(&priv->tx_dev.tx_dev_lock); |
| 397 | |
| 398 | if(cnt_txqbody(priv)>0){ |
| 399 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 0); |
| 400 | } |
| 401 | return result; |
| 402 | } |
| 403 | |
| 404 | static void rx_event_task(unsigned long dev) |
| 405 | { |
| 406 | ks_wlan_private *priv = (ks_wlan_private *)dev; |
| 407 | struct rx_device_buffer *rp; |
| 408 | |
| 409 | DPRINTK(4,"\n"); |
| 410 | |
| 411 | if(cnt_rxqbody(priv) > 0 && priv->dev_state >= DEVICE_STATE_BOOT){ |
| 412 | rp = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qhead]; |
| 413 | hostif_receive(priv, rp->data, rp->size); |
| 414 | inc_rxqhead(priv); |
| 415 | |
| 416 | if(cnt_rxqbody(priv) > 0){ |
| 417 | tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task); |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | return; |
| 422 | } |
| 423 | |
| 424 | static void ks_wlan_hw_rx(void *dev, uint16_t size) |
| 425 | { |
| 426 | ks_wlan_private *priv = (ks_wlan_private *)dev; |
| 427 | int retval; |
| 428 | struct rx_device_buffer *rx_buffer; |
| 429 | struct hostif_hdr *hdr; |
| 430 | unsigned char read_status; |
| 431 | unsigned short event=0; |
| 432 | |
| 433 | DPRINTK(4,"\n"); |
| 434 | |
| 435 | /* receive data */ |
| 436 | if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE-1)) { |
| 437 | /* in case of buffer overflow */ |
| 438 | DPRINTK(1,"rx buffer overflow \n"); |
| 439 | goto error_out; |
| 440 | } |
| 441 | rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail]; |
| 442 | |
| 443 | retval = ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0], hif_align_size(size)); |
| 444 | if(retval){ |
| 445 | goto error_out; |
| 446 | } |
| 447 | |
| 448 | /* length check */ |
| 449 | if(size > 2046 || size == 0){ |
| 450 | |
| 451 | DPRINTK(5,"-INVAILED DATA dump\n"); |
| 452 | print_buffer(&rx_buffer->data[0],32); |
| 453 | |
| 454 | /* rx_status update */ |
| 455 | read_status = READ_STATUS_IDLE; |
| 456 | retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); |
| 457 | if(retval){ |
| 458 | DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); |
| 459 | } |
| 460 | goto error_out; |
| 461 | } |
| 462 | |
| 463 | hdr = (struct hostif_hdr *)&rx_buffer->data[0]; |
| 464 | rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size); |
| 465 | event = hdr->event; |
| 466 | inc_rxqtail(priv); |
| 467 | |
| 468 | /* read status update */ |
| 469 | read_status = READ_STATUS_IDLE; |
| 470 | retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); |
| 471 | if(retval){ |
| 472 | DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); |
| 473 | } |
| 474 | DPRINTK(4, "READ_STATUS=%02X\n", read_status); |
| 475 | |
| 476 | if(atomic_read(&priv->psstatus.confirm_wait)){ |
| 477 | if(IS_HIF_CONF(event)){ |
| 478 | DPRINTK(4, "IS_HIF_CONF true !!\n"); |
| 479 | atomic_dec(&priv->psstatus.confirm_wait); |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | /* rx_event_task((void *)priv); */ |
| 484 | tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task); |
| 485 | |
| 486 | error_out: |
| 487 | return; |
| 488 | } |
| 489 | |
| 490 | static void ks7010_rw_function(struct work_struct *work) |
| 491 | { |
| 492 | struct hw_info_t *hw; |
| 493 | struct ks_wlan_private *priv; |
| 494 | unsigned char rw_data; |
| 495 | int retval; |
| 496 | |
| 497 | hw = container_of(work, struct hw_info_t, rw_wq.work); |
| 498 | priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw); |
| 499 | |
| 500 | DPRINTK(4,"\n"); |
| 501 | |
| 502 | |
| 503 | /* wiat after DOZE */ |
| 504 | if(time_after(priv->last_doze + ((30*HZ)/1000), jiffies )){ |
| 505 | DPRINTK(4, "wait after DOZE \n"); |
| 506 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 507 | return; |
| 508 | } |
| 509 | |
| 510 | /* wiat after WAKEUP */ |
| 511 | if(time_after(priv->last_wakeup + ((30*HZ)/1000), jiffies )){ |
| 512 | DPRINTK(4, "wait after WAKEUP \n"); |
| 513 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 514 | return; |
| 515 | } |
| 516 | |
| 517 | sdio_claim_host(priv->ks_wlan_hw.sdio_card->func); |
| 518 | |
| 519 | /* power save wakeup */ |
| 520 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE){ |
| 521 | if(cnt_txqbody(priv)>0){ |
| 522 | ks_wlan_hw_wakeup_request(priv); |
| 523 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 524 | } |
| 525 | goto err_out; |
| 526 | } |
| 527 | |
| 528 | /* sleep mode doze */ |
| 529 | if(atomic_read(&priv->sleepstatus.doze_request)==1){ |
| 530 | ks_wlan_hw_sleep_doze_request(priv); |
| 531 | goto err_out; |
| 532 | } |
| 533 | /* sleep mode wakeup */ |
| 534 | if(atomic_read(&priv->sleepstatus.wakeup_request)==1){ |
| 535 | ks_wlan_hw_sleep_wakeup_request(priv); |
| 536 | goto err_out; |
| 537 | } |
| 538 | |
| 539 | /* read (WriteStatus/ReadDataSize FN1:00_0014) */ |
| 540 | retval = ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data)); |
| 541 | if(retval){ |
| 542 | DPRINTK(1, " error : WSTATUS_RSIZE=%02X psstatus=%d\n", rw_data,atomic_read(&priv->psstatus.status)); |
| 543 | goto err_out; |
| 544 | } |
| 545 | DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data); |
| 546 | |
| 547 | if(rw_data&RSIZE_MASK){ /* Read schedule */ |
| 548 | ks_wlan_hw_rx((void *)priv, (uint16_t)(((rw_data&RSIZE_MASK)<<4))); |
| 549 | } |
| 550 | if((rw_data&WSTATUS_MASK)){ |
| 551 | tx_device_task((void *)priv); |
| 552 | } |
| 553 | _ks_wlan_hw_power_save(priv); |
| 554 | |
| 555 | err_out: |
| 556 | sdio_release_host(priv->ks_wlan_hw.sdio_card->func); |
| 557 | |
| 558 | return; |
| 559 | } |
| 560 | |
| 561 | |
| 562 | |
| 563 | static void ks_sdio_interrupt(struct sdio_func *func) |
| 564 | { |
| 565 | int retval; |
| 566 | struct ks_sdio_card *card; |
| 567 | ks_wlan_private *priv; |
| 568 | unsigned char status, rsize, rw_data; |
| 569 | |
| 570 | card = sdio_get_drvdata(func); |
| 571 | priv = card->priv; |
| 572 | DPRINTK(4, "\n"); |
| 573 | |
| 574 | if(priv->dev_state >= DEVICE_STATE_BOOT){ |
| 575 | retval = ks7010_sdio_read(priv, INT_PENDING, &status, sizeof(status)); |
| 576 | if(retval){ |
| 577 | DPRINTK(1, "read INT_PENDING Failed!!(%d)\n",retval); |
| 578 | goto intr_out; |
| 579 | } |
| 580 | DPRINTK(4, "INT_PENDING=%02X\n", rw_data); |
| 581 | |
| 582 | /* schedule task for interrupt status */ |
| 583 | /* bit7 -> Write General Communication B register */ |
| 584 | /* read (General Communication B register) */ |
| 585 | /* bit5 -> Write Status Idle */ |
| 586 | /* bit2 -> Read Status Busy */ |
| 587 | if(status&INT_GCR_B || atomic_read(&priv->psstatus.status)==PS_SNOOZE){ |
| 588 | retval = ks7010_sdio_read(priv, GCR_B, &rw_data, sizeof(rw_data)); |
| 589 | if(retval){ |
| 590 | DPRINTK(1, " error : GCR_B=%02X\n", rw_data); |
| 591 | goto intr_out; |
| 592 | } |
| 593 | /* DPRINTK(1, "GCR_B=%02X\n", rw_data); */ |
| 594 | if(rw_data == GCR_B_ACTIVE){ |
| 595 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE){ |
| 596 | atomic_set(&priv->psstatus.status, PS_WAKEUP); |
| 597 | priv->wakeup_count=0; |
| 598 | } |
| 599 | complete(&priv->psstatus.wakeup_wait); |
| 600 | } |
| 601 | |
| 602 | |
| 603 | } |
| 604 | |
| 605 | do{ |
| 606 | /* read (WriteStatus/ReadDataSize FN1:00_0014) */ |
| 607 | retval = ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data)); |
| 608 | if(retval){ |
| 609 | DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n", rw_data); |
| 610 | goto intr_out; |
| 611 | } |
| 612 | DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data); |
| 613 | rsize=rw_data&RSIZE_MASK; |
| 614 | if(rsize){ /* Read schedule */ |
| 615 | ks_wlan_hw_rx((void *)priv, (uint16_t)(((rsize)<<4))); |
| 616 | } |
| 617 | if(rw_data&WSTATUS_MASK){ |
| 618 | #if 0 |
| 619 | if(status&INT_WRITE_STATUS && !cnt_txqbody(priv)){ |
| 620 | /* dummy write for interrupt clear */ |
| 621 | rw_data =0; |
| 622 | retval = ks7010_sdio_write(priv, DATA_WINDOW, &rw_data, sizeof(rw_data)); |
| 623 | if (retval) { |
| 624 | DPRINTK(1, "write DATA_WINDOW Failed!!(%d)\n",retval); |
| 625 | } |
| 626 | status &= ~INT_WRITE_STATUS; |
| 627 | } |
| 628 | else{ |
| 629 | #endif |
| 630 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE){ |
| 631 | if(cnt_txqbody(priv)){ |
| 632 | ks_wlan_hw_wakeup_request(priv); |
| 633 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 1); |
| 634 | return; |
| 635 | } |
| 636 | } |
| 637 | else{ |
| 638 | tx_device_task((void *)priv); |
| 639 | } |
| 640 | // } |
| 641 | } |
| 642 | }while(rsize); |
| 643 | } |
| 644 | |
| 645 | intr_out: |
| 646 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 0); |
| 647 | return; |
| 648 | } |
| 649 | |
| 650 | static int trx_device_init( ks_wlan_private *priv ) |
| 651 | { |
| 652 | /* initialize values (tx) */ |
| 653 | priv->tx_dev.qtail = priv->tx_dev.qhead = 0; |
| 654 | |
| 655 | /* initialize values (rx) */ |
| 656 | priv->rx_dev.qtail = priv->rx_dev.qhead = 0; |
| 657 | |
| 658 | /* initialize spinLock (tx,rx) */ |
| 659 | spin_lock_init(&priv->tx_dev.tx_dev_lock); |
| 660 | spin_lock_init(&priv->rx_dev.rx_dev_lock); |
| 661 | |
| 662 | tasklet_init(&priv->ks_wlan_hw.rx_bh_task, rx_event_task, (unsigned long)priv); |
| 663 | |
| 664 | return 0; |
| 665 | } |
| 666 | |
| 667 | static void trx_device_exit( ks_wlan_private *priv ) |
| 668 | { |
| 669 | struct tx_device_buffer *sp; |
| 670 | |
| 671 | /* tx buffer clear */ |
| 672 | while (cnt_txqbody(priv)>0) { |
| 673 | sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead]; |
| 674 | kfree(sp->sendp); /* allocated memory free */ |
| 675 | if (sp->complete_handler != NULL) /* TX Complete */ |
| 676 | (*sp->complete_handler)(sp->arg1, sp->arg2); |
| 677 | inc_txqhead(priv); |
| 678 | } |
| 679 | |
| 680 | tasklet_kill(&priv->ks_wlan_hw.rx_bh_task); |
| 681 | |
| 682 | return; |
| 683 | } |
| 684 | static int ks7010_sdio_update_index(ks_wlan_private *priv, u32 index) |
| 685 | { |
| 686 | int rc=0; |
| 687 | int retval; |
| 688 | unsigned char *data_buf; |
| 689 | data_buf = NULL; |
| 690 | |
| 691 | data_buf = kmalloc(sizeof(u32), GFP_KERNEL); |
| 692 | if(!data_buf){ rc = 1; goto error_out; } |
| 693 | |
| 694 | memcpy(data_buf, &index, sizeof(index)); |
| 695 | retval = ks7010_sdio_write(priv, WRITE_INDEX, data_buf, sizeof(index)); |
| 696 | if(retval){ rc = 2; goto error_out; } |
| 697 | |
| 698 | retval = ks7010_sdio_write(priv, READ_INDEX, data_buf, sizeof(index)); |
| 699 | if(retval){ rc = 3; goto error_out; } |
| 700 | error_out: |
| 701 | if(data_buf) kfree(data_buf); |
| 702 | return rc; |
| 703 | } |
| 704 | |
| 705 | #define ROM_BUFF_SIZE (64*1024) |
| 706 | static int ks7010_sdio_data_compare(ks_wlan_private *priv, u32 address, |
| 707 | unsigned char *data, unsigned int size) |
| 708 | { |
| 709 | int rc=0; |
| 710 | int retval; |
| 711 | unsigned char *read_buf; |
| 712 | read_buf = NULL; |
| 713 | read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); |
| 714 | if(!read_buf){ rc = 1; goto error_out; } |
| 715 | retval = ks7010_sdio_read(priv, address, read_buf, size); |
| 716 | if(retval){ rc = 2; goto error_out; } |
| 717 | retval = memcmp(data, read_buf, size); |
| 718 | |
| 719 | if(retval){ |
| 720 | DPRINTK(0, "data compare error (%d) \n",retval); rc = 3; goto error_out; |
| 721 | } |
| 722 | error_out: |
| 723 | if(read_buf) kfree(read_buf); |
| 724 | return rc; |
| 725 | } |
| 726 | #ifndef NO_FIRMWARE_CLASS |
| 727 | #include <linux/firmware.h> |
| 728 | #endif |
| 729 | static int ks79xx_upload_firmware(ks_wlan_private *priv, struct ks_sdio_card *card) |
| 730 | { |
| 731 | unsigned int size, offset, n = 0; |
| 732 | unsigned char *rom_buf; |
| 733 | unsigned char rw_data =0; |
| 734 | int retval, rc=0; |
| 735 | #ifndef NO_FIRMWARE_CLASS |
| 736 | int length; |
| 737 | const struct firmware *fw_entry = NULL; |
| 738 | #else |
| 739 | int orgfsuid, orgfsgid; |
| 740 | struct file *srcf; |
| 741 | mm_segment_t orgfs; |
| 742 | #endif |
| 743 | |
| 744 | rom_buf = NULL; |
| 745 | |
| 746 | /* buffer allocate */ |
| 747 | rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); |
| 748 | if(!rom_buf){ rc = 3; goto error_out0; } |
| 749 | |
| 750 | |
| 751 | sdio_claim_host(card->func); |
| 752 | |
| 753 | /* Firmware running ? */ |
| 754 | retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data)); |
| 755 | if(rw_data == GCR_A_RUN){ |
| 756 | DPRINTK( 0, "MAC firmware running ...\n"); |
| 757 | rc = 0; |
| 758 | goto error_out0; |
| 759 | } |
| 760 | |
| 761 | #ifndef NO_FIRMWARE_CLASS |
| 762 | if(request_firmware(&fw_entry, priv->reg.rom_file, &priv->ks_wlan_hw.sdio_card->func->dev)!=0){ |
| 763 | DPRINTK(1,"error request_firmware() file=%s\n", priv->reg.rom_file); |
| 764 | return 1; |
| 765 | } |
| 766 | DPRINTK(4,"success request_firmware() file=%s size=%d\n", priv->reg.rom_file, fw_entry->size); |
| 767 | length = fw_entry->size; |
| 768 | #else |
| 769 | orgfsuid=current->fsuid; |
| 770 | orgfsgid=current->fsgid; |
| 771 | current->fsuid=current->fsgid=0; |
| 772 | orgfs=get_fs(); |
| 773 | set_fs(KERNEL_DS); |
| 774 | |
| 775 | srcf = filp_open(romfile, O_RDONLY, 0); |
| 776 | if (IS_ERR(srcf)) { |
| 777 | DPRINTK(1, "error %ld opening %s\n", -PTR_ERR(srcf),romfile); |
| 778 | rc = 1; |
| 779 | goto error_out1; |
| 780 | } |
| 781 | |
| 782 | if (!(srcf->f_op && srcf->f_op->read)) { |
| 783 | DPRINTK(1, "%s does not have a read method\n", romfile); |
| 784 | rc = 2; |
| 785 | goto error_out2; |
| 786 | } |
| 787 | #endif |
| 788 | |
| 789 | /* Load Program */ |
| 790 | n = 0; |
| 791 | do { |
| 792 | #ifndef NO_FIRMWARE_CLASS |
| 793 | if(length >= ROM_BUFF_SIZE){ |
| 794 | size = ROM_BUFF_SIZE; |
| 795 | length = length - ROM_BUFF_SIZE; |
| 796 | } |
| 797 | else{ |
| 798 | size=length; |
| 799 | length=0; |
| 800 | } |
| 801 | DPRINTK(4, "size = %d\n",size); |
| 802 | if(size == 0) break; |
| 803 | memcpy(rom_buf,fw_entry->data+n,size); |
| 804 | #else |
| 805 | /* The object must have a read method */ |
| 806 | size = srcf->f_op->read(srcf, rom_buf, ROM_BUFF_SIZE, &srcf->f_pos); |
| 807 | if (size < 0) { |
| 808 | DPRINTK(1, "Read %s error %d\n", priv->reg.rom_file, -retval); |
| 809 | rc = 5; |
| 810 | goto error_out2; |
| 811 | } |
| 812 | else if (size == 0) break; |
| 813 | #endif |
| 814 | /* Update write index */ |
| 815 | offset = n; |
| 816 | retval = ks7010_sdio_update_index(priv, KS7010_IRAM_ADDRESS+offset); |
| 817 | if(retval){ rc = 6; goto error_out1; } |
| 818 | |
| 819 | /* Write data */ |
| 820 | retval = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size); |
| 821 | if(retval){ rc = 8; goto error_out1; } |
| 822 | |
| 823 | /* compare */ |
| 824 | retval = ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size); |
| 825 | if(retval){ rc = 9; goto error_out1; } |
| 826 | n += size; |
| 827 | |
| 828 | }while(size); |
| 829 | |
| 830 | /* Remap request */ |
| 831 | rw_data = GCR_A_REMAP; |
| 832 | retval = ks7010_sdio_write(priv, GCR_A, &rw_data, sizeof(rw_data)); |
| 833 | if(retval){ |
| 834 | rc = 11; |
| 835 | goto error_out1; |
| 836 | } |
| 837 | DPRINTK( 4, " REMAP Request : GCR_A=%02X\n", rw_data); |
| 838 | |
| 839 | /* Firmware running check */ |
| 840 | for (n = 0; n < 50; ++n) { |
| 841 | mdelay(10);/* wait_ms(10); */ |
| 842 | retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data)); |
| 843 | if(retval){ rc = 11; goto error_out1; } |
| 844 | if(rw_data == GCR_A_RUN) break; |
| 845 | } |
| 846 | DPRINTK(4, "firmware wakeup (%d)!!!!\n",n); |
| 847 | if ((50) <= n) { |
| 848 | DPRINTK(1, "firmware can't start\n"); |
| 849 | rc = 12; |
| 850 | goto error_out1; |
| 851 | } |
| 852 | |
| 853 | rc = 0; |
| 854 | |
| 855 | #ifdef NO_FIRMWARE_CLASS |
| 856 | error_out2: |
| 857 | retval=filp_close(srcf ,NULL); |
| 858 | if (retval) |
| 859 | DPRINTK(1, "error %d closing %s\n", -retval,priv->reg.rom_file); |
| 860 | |
| 861 | error_out1: |
| 862 | set_fs(orgfs); |
| 863 | current->fsuid=orgfsuid; |
| 864 | current->fsgid=orgfsgid; |
| 865 | #else |
| 866 | error_out1: |
| 867 | release_firmware(fw_entry); |
| 868 | #endif |
| 869 | error_out0: |
| 870 | sdio_release_host(card->func); |
| 871 | if(rom_buf) |
| 872 | kfree(rom_buf); |
| 873 | return rc; |
| 874 | } |
| 875 | |
| 876 | static void card_init_task(struct work_struct *work) |
| 877 | { |
| 878 | struct hw_info_t *hw; |
| 879 | struct ks_wlan_private *priv; |
| 880 | |
| 881 | hw = container_of(work, struct hw_info_t, init_task); |
| 882 | priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw); |
| 883 | |
| 884 | DPRINTK(5,"\ncard_init_task()\n"); |
| 885 | |
| 886 | /* init_waitqueue_head(&priv->confirm_wait); */ |
| 887 | init_completion(&priv->confirm_wait); |
| 888 | |
| 889 | DPRINTK(5,"init_completion()\n"); |
| 890 | |
| 891 | /* get mac address & firmware version */ |
| 892 | hostif_sme_enqueue(priv, SME_START); |
| 893 | |
| 894 | DPRINTK(5,"hostif_sme_enqueu()\n"); |
| 895 | |
| 896 | if(!wait_for_completion_interruptible_timeout(&priv->confirm_wait,5*HZ)){ |
| 897 | DPRINTK(1,"wait time out!! SME_START\n"); |
| 898 | } |
| 899 | |
| 900 | if(priv->mac_address_valid && priv->version_size){ |
| 901 | priv->dev_state = DEVICE_STATE_PREINIT; |
| 902 | } |
| 903 | |
| 904 | hostif_sme_enqueue(priv, SME_GET_EEPROM_CKSUM); |
| 905 | |
| 906 | /* load initial wireless parameter */ |
| 907 | hostif_sme_enqueue(priv, SME_STOP_REQUEST); |
| 908 | |
| 909 | hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_REQUEST); |
| 910 | hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_REQUEST); |
| 911 | |
| 912 | hostif_sme_enqueue(priv, SME_WEP_INDEX_REQUEST); |
| 913 | hostif_sme_enqueue(priv, SME_WEP_KEY1_REQUEST); |
| 914 | hostif_sme_enqueue(priv, SME_WEP_KEY2_REQUEST); |
| 915 | hostif_sme_enqueue(priv, SME_WEP_KEY3_REQUEST); |
| 916 | hostif_sme_enqueue(priv, SME_WEP_KEY4_REQUEST); |
| 917 | |
| 918 | hostif_sme_enqueue(priv, SME_WEP_FLAG_REQUEST); |
| 919 | hostif_sme_enqueue(priv, SME_RSN_ENABLED_REQUEST); |
| 920 | hostif_sme_enqueue(priv, SME_MODE_SET_REQUEST); |
| 921 | hostif_sme_enqueue(priv, SME_START_REQUEST); |
| 922 | |
| 923 | if(!wait_for_completion_interruptible_timeout(&priv->confirm_wait,5*HZ)){ |
| 924 | DPRINTK(1,"wait time out!! wireless parameter set\n"); |
| 925 | } |
| 926 | |
| 927 | if(priv->dev_state >= DEVICE_STATE_PREINIT){ |
| 928 | DPRINTK(1, "DEVICE READY!!\n"); |
| 929 | priv->dev_state = DEVICE_STATE_READY; |
| 930 | reg_net = register_netdev (priv->net_dev); |
| 931 | DPRINTK(3, "register_netdev=%d\n",reg_net); |
| 932 | } |
| 933 | else { |
| 934 | DPRINTK(1, "dev_state=%d\n",priv->dev_state); |
| 935 | } |
| 936 | } |
| 937 | |
| 938 | static struct sdio_driver ks7010_sdio_driver = { |
| 939 | .name = "ks7910_sdio", |
| 940 | .id_table = if_sdio_ids, |
| 941 | .probe = ks7910_sdio_probe, |
| 942 | .remove = ks7910_sdio_remove, |
| 943 | }; |
| 944 | |
| 945 | |
| 946 | extern int ks_wlan_net_start(struct net_device *dev); |
| 947 | extern int ks_wlan_net_stop(struct net_device *dev); |
| 948 | |
| 949 | static int ks7910_sdio_probe(struct sdio_func *func, const struct sdio_device_id *device) |
| 950 | { |
| 951 | ks_wlan_private *priv; |
| 952 | struct ks_sdio_card *card; |
| 953 | struct net_device *netdev; |
| 954 | unsigned char rw_data; |
| 955 | int i=0, ret; |
| 956 | |
| 957 | DPRINTK(5, "ks7910_sdio_probe()\n"); |
| 958 | |
| 959 | priv = NULL; |
| 960 | netdev=NULL; |
| 961 | |
| 962 | |
| 963 | /* initilize ks_sdio_card */ |
| 964 | card = kzalloc(sizeof(struct ks_sdio_card), GFP_KERNEL); |
| 965 | if (!card) |
| 966 | return -ENOMEM; |
| 967 | |
| 968 | card->func = func; |
| 969 | card->model = 0x10; |
| 970 | spin_lock_init(&card->lock); |
| 971 | |
| 972 | /* select model */ |
| 973 | for (i = 0;i < ARRAY_SIZE(ks_sdio_models);i++) { |
| 974 | if (card->model == ks_sdio_models[i].model) |
| 975 | break; |
| 976 | } |
| 977 | |
| 978 | if (i == ARRAY_SIZE(ks_sdio_models)) { |
| 979 | DPRINTK(5, "unkown card model 0x%x\n", card->model); |
| 980 | goto error; |
| 981 | } |
| 982 | |
| 983 | card->firmware = ks_sdio_models[i].firmware; |
| 984 | |
| 985 | |
| 986 | /*** Initialize SDIO ***/ |
| 987 | sdio_claim_host(func); |
| 988 | |
| 989 | /* bus setting */ |
| 990 | /* Issue config request to override clock rate */ |
| 991 | |
| 992 | /* function blocksize set */ |
| 993 | ret = sdio_set_block_size(func, KS7010_IO_BLOCK_SIZE); |
| 994 | DPRINTK(5, "multi_block=%d sdio_set_block_size()=%d %d\n", func->card->cccr.multi_block, func->cur_blksize, ret); |
| 995 | |
| 996 | /* Allocate the slot current */ |
| 997 | |
| 998 | /* function enable */ |
| 999 | ret = sdio_enable_func(func); |
| 1000 | DPRINTK(5, "sdio_enable_func() %d\n", ret); |
| 1001 | if (ret) |
| 1002 | goto error_free_card; |
| 1003 | |
| 1004 | /* interrupt disable */ |
| 1005 | sdio_writeb(func, 0, INT_ENABLE, &ret); |
| 1006 | if (ret) |
| 1007 | goto error_free_card; |
| 1008 | sdio_writeb(func, 0xff, INT_PENDING, &ret); |
| 1009 | if (ret) |
| 1010 | goto error_disable_func; |
| 1011 | |
| 1012 | /* setup interrupt handler */ |
| 1013 | ret = sdio_claim_irq(func, ks_sdio_interrupt); |
| 1014 | if (ret) |
| 1015 | goto error_disable_func; |
| 1016 | |
| 1017 | sdio_release_host(func); |
| 1018 | |
| 1019 | sdio_set_drvdata(func, card); |
| 1020 | |
| 1021 | DPRINTK(5, "class = 0x%X, vendor = 0x%X, " |
| 1022 | "device = 0x%X\n", |
| 1023 | func->class, func->vendor, func->device); |
| 1024 | |
| 1025 | |
| 1026 | /* private memory allocate */ |
| 1027 | netdev = alloc_etherdev(sizeof(*priv)); |
| 1028 | if (netdev == NULL) { |
| 1029 | printk (KERN_ERR "ks79xx : Unable to alloc new net device\n"); |
| 1030 | goto error_release_irq; |
| 1031 | } |
| 1032 | if (dev_alloc_name(netdev, netdev->name) < 0) { |
| 1033 | printk (KERN_ERR "ks79xx : Couldn't get name!\n"); |
| 1034 | goto error_free_netdev; |
| 1035 | } |
| 1036 | |
| 1037 | priv = netdev_priv(netdev); |
| 1038 | |
| 1039 | card->priv = priv; |
| 1040 | SET_NETDEV_DEV(netdev, &card->func->dev); /* for create sysfs symlinks */ |
| 1041 | |
| 1042 | /* private memory initialize */ |
| 1043 | priv->ks_wlan_hw.sdio_card = card; |
| 1044 | init_completion(&priv->ks_wlan_hw.ks7010_sdio_wait); |
| 1045 | priv->ks_wlan_hw.read_buf = NULL; |
| 1046 | priv->ks_wlan_hw.read_buf = kmalloc(RX_DATA_SIZE, GFP_KERNEL); |
| 1047 | if(!priv->ks_wlan_hw.read_buf){ |
| 1048 | goto error_free_netdev; |
| 1049 | } |
| 1050 | priv->dev_state = DEVICE_STATE_PREBOOT; |
| 1051 | priv->net_dev = netdev; |
| 1052 | priv->firmware_version[0] = '\0'; |
| 1053 | priv->version_size = 0; |
| 1054 | priv->last_doze = jiffies; /* set current jiffies */ |
| 1055 | priv->last_doze = jiffies; |
| 1056 | memset(&priv->nstats, 0, sizeof(priv->nstats)); |
| 1057 | memset(&priv->wstats, 0, sizeof(priv->wstats)); |
| 1058 | |
| 1059 | /* sleep mode */ |
| 1060 | atomic_set(&priv->sleepstatus.doze_request,0); |
| 1061 | atomic_set(&priv->sleepstatus.wakeup_request,0); |
| 1062 | atomic_set(&priv->sleepstatus.wakeup_request,0); |
| 1063 | |
| 1064 | trx_device_init(priv); |
| 1065 | hostif_init(priv); |
| 1066 | ks_wlan_net_start(netdev); |
| 1067 | |
| 1068 | /* Read config file */ |
| 1069 | ret = ks_wlan_read_config_file(priv); |
| 1070 | if (ret) { |
| 1071 | printk(KERN_ERR "ks79xx: read configuration file failed !! retern code = %d\n", ret); |
| 1072 | goto error_free_read_buf; |
| 1073 | } |
| 1074 | |
| 1075 | /* Upload firmware */ |
| 1076 | ret = ks79xx_upload_firmware(priv, card); /* firmware load */ |
| 1077 | if(ret){ |
| 1078 | printk(KERN_ERR "ks79xx: firmware load failed !! retern code = %d\n", ret); |
| 1079 | goto error_free_read_buf; |
| 1080 | } |
| 1081 | |
| 1082 | /* interrupt setting */ |
| 1083 | /* clear Interrupt status write (ARMtoSD_InterruptPending FN1:00_0024) */ |
| 1084 | rw_data = 0xff; |
| 1085 | sdio_claim_host(func); |
| 1086 | ret = ks7010_sdio_write(priv, INT_PENDING, &rw_data, sizeof(rw_data)); |
| 1087 | sdio_release_host(func); |
| 1088 | if(ret){ |
| 1089 | DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data); |
| 1090 | } |
| 1091 | DPRINTK(4, " clear Interrupt : INT_PENDING=%02X\n", rw_data); |
| 1092 | |
| 1093 | |
| 1094 | /* enable ks7010sdio interrupt (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS) */ |
| 1095 | rw_data = (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS); |
| 1096 | sdio_claim_host(func); |
| 1097 | ret = ks7010_sdio_write(priv, INT_ENABLE, &rw_data, sizeof(rw_data)); |
| 1098 | sdio_release_host(func); |
| 1099 | if(ret){ |
| 1100 | DPRINTK(1, " error : INT_ENABLE=%02X\n", rw_data); |
| 1101 | } |
| 1102 | DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", rw_data); |
| 1103 | priv->dev_state = DEVICE_STATE_BOOT; |
| 1104 | |
| 1105 | priv->ks_wlan_hw.ks7010sdio_wq = create_workqueue("ks7010sdio_wq"); |
| 1106 | if(!priv->ks_wlan_hw.ks7010sdio_wq){ |
| 1107 | DPRINTK(1, "create_workqueue failed !!\n"); |
| 1108 | goto error_free_read_buf; |
| 1109 | } |
| 1110 | |
| 1111 | priv->ks_wlan_hw.ks7010sdio_init = create_singlethread_workqueue("ks7010sdio_init"); |
| 1112 | if(!priv->ks_wlan_hw.ks7010sdio_init){ |
| 1113 | DPRINTK(1, "create_workqueue failed !!\n"); |
| 1114 | goto error_free_sdio_wq; |
| 1115 | } |
| 1116 | |
| 1117 | INIT_WORK(&priv->ks_wlan_hw.init_task, card_init_task); |
| 1118 | INIT_DELAYED_WORK(&priv->ks_wlan_hw.rw_wq, ks7010_rw_function); |
| 1119 | |
| 1120 | queue_work(priv->ks_wlan_hw.ks7010sdio_init, &priv->ks_wlan_hw.init_task); |
| 1121 | |
| 1122 | return 0; |
| 1123 | |
| 1124 | error_free_sdio_wq: |
| 1125 | flush_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); |
| 1126 | destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); |
| 1127 | priv->ks_wlan_hw.ks7010sdio_wq = NULL; |
| 1128 | error_free_read_buf: |
| 1129 | kfree(priv->ks_wlan_hw.read_buf); |
| 1130 | priv->ks_wlan_hw.read_buf = NULL; |
| 1131 | error_free_netdev: |
| 1132 | free_netdev(priv->net_dev); |
| 1133 | card->priv = NULL; |
| 1134 | error_release_irq: |
| 1135 | sdio_claim_host(func); |
| 1136 | sdio_release_irq(func); |
| 1137 | error_disable_func: |
| 1138 | sdio_disable_func(func); |
| 1139 | error_free_card: |
| 1140 | sdio_release_host(func); |
| 1141 | sdio_set_drvdata(func, NULL); |
| 1142 | kfree(card); |
| 1143 | error: |
| 1144 | return -ENODEV; |
| 1145 | } |
| 1146 | |
| 1147 | static void ks7910_sdio_remove(struct sdio_func *func) |
| 1148 | { |
| 1149 | int ret; |
| 1150 | struct ks_sdio_card *card; |
| 1151 | struct ks_wlan_private *priv; |
| 1152 | struct net_device *netdev; |
| 1153 | DPRINTK(1, "ks7910_sdio_remove()\n"); |
| 1154 | |
| 1155 | card = sdio_get_drvdata(func); |
| 1156 | |
| 1157 | if(card == NULL) |
| 1158 | return; |
| 1159 | |
| 1160 | DPRINTK(1, "priv = card->priv\n"); |
| 1161 | priv = card->priv; |
| 1162 | netdev = priv->net_dev; |
| 1163 | if(priv){ |
| 1164 | ks_wlan_net_stop(netdev); |
| 1165 | DPRINTK(1, "ks_wlan_net_stop\n"); |
| 1166 | |
| 1167 | /* interrupt disable */ |
| 1168 | sdio_claim_host(func); |
| 1169 | sdio_writeb(func, 0, INT_ENABLE, &ret); |
| 1170 | sdio_writeb(func, 0xff, INT_PENDING, &ret); |
| 1171 | sdio_release_host(func); |
| 1172 | DPRINTK(1, "interrupt disable\n"); |
| 1173 | |
| 1174 | /* send stop request to MAC */ |
| 1175 | { |
| 1176 | struct hostif_stop_request_t *pp; |
| 1177 | pp = (struct hostif_stop_request_t *)kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL ); |
| 1178 | if (pp==NULL) { |
| 1179 | DPRINTK(3,"allocate memory failed..\n"); |
| 1180 | return; /* to do goto ni suru*/ |
| 1181 | } |
| 1182 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1183 | pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ); |
| 1184 | |
| 1185 | sdio_claim_host(func); |
| 1186 | write_to_device(priv, (unsigned char *) pp, hif_align_size(sizeof(*pp))); |
| 1187 | sdio_release_host(func); |
| 1188 | kfree(pp); |
| 1189 | } |
| 1190 | DPRINTK(1, "STOP Req\n"); |
| 1191 | |
| 1192 | if(priv->ks_wlan_hw.ks7010sdio_wq){ |
| 1193 | flush_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); |
| 1194 | destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); |
| 1195 | } |
| 1196 | DPRINTK(1, "destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);\n"); |
| 1197 | |
| 1198 | if(priv->ks_wlan_hw.ks7010sdio_init){ |
| 1199 | flush_workqueue(priv->ks_wlan_hw.ks7010sdio_init); |
| 1200 | destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_init); |
| 1201 | } |
| 1202 | DPRINTK(1, "destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_init);\n"); |
| 1203 | |
| 1204 | hostif_exit(priv); |
| 1205 | DPRINTK(1, "hostif_exit\n"); |
| 1206 | |
| 1207 | if(!reg_net) |
| 1208 | unregister_netdev(netdev); |
| 1209 | DPRINTK(1, "unregister_netdev\n"); |
| 1210 | |
| 1211 | trx_device_exit(priv); |
| 1212 | if(priv->ks_wlan_hw.read_buf){ |
| 1213 | kfree(priv->ks_wlan_hw.read_buf); |
| 1214 | } |
| 1215 | free_netdev(priv->net_dev); |
| 1216 | card->priv = NULL; |
| 1217 | } |
| 1218 | |
| 1219 | sdio_claim_host(func); |
| 1220 | sdio_release_irq(func); |
| 1221 | DPRINTK(1, "sdio_release_irq()\n"); |
| 1222 | sdio_disable_func(func); |
| 1223 | DPRINTK(1, "sdio_disable_func()\n"); |
| 1224 | sdio_release_host(func); |
| 1225 | |
| 1226 | sdio_set_drvdata(func, NULL); |
| 1227 | |
| 1228 | kfree(card); |
| 1229 | DPRINTK(1, "kfree()\n"); |
| 1230 | |
| 1231 | |
| 1232 | DPRINTK(5," Bye !!\n"); |
| 1233 | return; |
| 1234 | } |
| 1235 | |
| 1236 | static int __init ks7010_sdio_init( void ) |
| 1237 | { |
| 1238 | int status; |
| 1239 | printk(KERN_INFO "ks7010_sdio : %s %s\n" ,__DATE__,__TIME__); |
| 1240 | |
| 1241 | /* register with bus driver core */ |
| 1242 | status = sdio_register_driver(&ks7010_sdio_driver); |
| 1243 | if(status != 0){ |
| 1244 | DPRINTK(1,"ks79xx_sdio : failed to register with bus driver, %d\n", status ); |
| 1245 | } |
| 1246 | return status; |
| 1247 | } |
| 1248 | |
| 1249 | static void __exit ks7010_sdio_exit( void ) |
| 1250 | { |
| 1251 | DPRINTK(5," \n"); |
| 1252 | sdio_unregister_driver(&ks7010_sdio_driver); |
| 1253 | return; |
| 1254 | } |
| 1255 | |
| 1256 | module_init(ks7010_sdio_init); |
| 1257 | module_exit(ks7010_sdio_exit); |
| 1258 | |
| 1259 | MODULE_AUTHOR("Qi-Hardware based on KeyStream driver"); |
| 1260 | MODULE_DESCRIPTION("Driver for KeyStream, KS7010 based SDIO cards. "); |
| 1261 | #ifdef MODULE_LICENSE |
| 1262 | MODULE_LICENSE("GPL"); |
| 1263 | #endif |
| 1264 | MODULE_SUPPORTED_DEVICE("KS7910"); |
drivers/net/wireless/ks7010/ks_hostif.c |
| 1 | /* |
| 2 | * Driver for KeyStream wireless LAN cards. |
| 3 | * |
| 4 | * ks_hostif.c |
| 5 | * $Id: ks_hostif.c 996 2009-09-14 02:54:21Z sekine $ |
| 6 | * |
| 7 | * Copyright (C) 2005-2008 KeyStream Corp. |
| 8 | * Copyright (C) 2009 Renesas Technology Corp. |
| 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it undr the terms of the GNU General Public License version 2 as |
| 12 | * published by the Free Sotware Foundation. |
| 13 | */ |
| 14 | |
| 15 | #include "ks_wlan.h" |
| 16 | #include "ks_debug.h" |
| 17 | #include "ks_hostif.h" |
| 18 | #include "eap_packet.h" |
| 19 | #include "michael_mic.h" |
| 20 | |
| 21 | #include <linux/if_ether.h> |
| 22 | #include <linux/if_arp.h> |
| 23 | |
| 24 | /* Include Wireless Extension definition and check version */ |
| 25 | #ifndef WIRELESS_EXT |
| 26 | #include <linux/wireless.h> |
| 27 | #endif /* WIRELESS_EXT */ |
| 28 | #if WIRELESS_EXT > 12 |
| 29 | #include <net/iw_handler.h> /* New driver API */ |
| 30 | #endif /* WIRELESS_EXT > 12 */ |
| 31 | |
| 32 | extern int ks_wlan_hw_tx(ks_wlan_private *priv, void *p, unsigned long size, |
| 33 | void (*complete_handler)(void *arg1, void *arg2), |
| 34 | void *arg1, void *arg2 ); |
| 35 | extern void send_packet_complete(void *, void *); |
| 36 | |
| 37 | extern void ks_wlan_hw_wakeup_request(ks_wlan_private *priv); |
| 38 | extern int ks_wlan_hw_power_save(ks_wlan_private *priv); |
| 39 | |
| 40 | /* macro */ |
| 41 | #define inc_smeqhead(priv) \ |
| 42 | ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE ) |
| 43 | #define inc_smeqtail(priv) \ |
| 44 | ( priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE ) |
| 45 | #define cnt_smeqbody(priv) \ |
| 46 | (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE ) |
| 47 | |
| 48 | #define KS_WLAN_MEM_FLAG (GFP_ATOMIC) |
| 49 | |
| 50 | static |
| 51 | inline u8 get_BYTE(ks_wlan_private *priv) |
| 52 | { |
| 53 | u8 data; |
| 54 | data = *(priv->rxp)++; |
| 55 | /* length check in advance ! */ |
| 56 | --(priv->rx_size); |
| 57 | return data; |
| 58 | } |
| 59 | |
| 60 | static |
| 61 | inline u16 get_WORD(ks_wlan_private *priv) |
| 62 | { |
| 63 | u16 data; |
| 64 | data = (get_BYTE(priv) & 0xff); |
| 65 | data |= ((get_BYTE(priv) << 8) & 0xff00); |
| 66 | return data; |
| 67 | } |
| 68 | |
| 69 | static |
| 70 | inline u32 get_DWORD(ks_wlan_private *priv) |
| 71 | { |
| 72 | u32 data; |
| 73 | data = (get_BYTE(priv) & 0xff); |
| 74 | data |= ((get_BYTE(priv) << 8) & 0x0000ff00); |
| 75 | data |= ((get_BYTE(priv) << 16) & 0x00ff0000); |
| 76 | data |= ((get_BYTE(priv) << 24) & 0xff000000); |
| 77 | return data; |
| 78 | } |
| 79 | |
| 80 | void ks_wlan_hw_wakeup_task(struct work_struct *work) |
| 81 | { |
| 82 | ks_wlan_private *priv = container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task); |
| 83 | int ps_status = atomic_read(&priv->psstatus.status); |
| 84 | |
| 85 | if(ps_status==PS_SNOOZE){ |
| 86 | ks_wlan_hw_wakeup_request(priv); |
| 87 | if(!wait_for_completion_interruptible_timeout(&priv->psstatus.wakeup_wait,HZ/50)){ /* 20ms timeout */ |
| 88 | DPRINTK(1,"wake up timeout !!!\n"); |
| 89 | schedule_work(&priv->ks_wlan_wakeup_task); |
| 90 | return; |
| 91 | } |
| 92 | } |
| 93 | else{ |
| 94 | DPRINTK(1,"ps_status=%d\n",ps_status); |
| 95 | } |
| 96 | |
| 97 | /* power save */ |
| 98 | if(atomic_read(&priv->sme_task.count) > 0){ |
| 99 | DPRINTK(4,"sme task enable.\n"); |
| 100 | tasklet_enable(&priv->sme_task); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | static |
| 105 | int ks_wlan_do_power_save(ks_wlan_private *priv) |
| 106 | { |
| 107 | int rc=0; |
| 108 | |
| 109 | DPRINTK(4,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status)); |
| 110 | |
| 111 | #ifdef _SDIO_ |
| 112 | if((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS){ |
| 113 | hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST); |
| 114 | } |
| 115 | else{ |
| 116 | priv->dev_state = DEVICE_STATE_READY; |
| 117 | } |
| 118 | #else |
| 119 | if((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS){ |
| 120 | switch(atomic_read(&priv->psstatus.status)){ |
| 121 | case PS_ACTIVE_SET: |
| 122 | case PS_WAKEUP: |
| 123 | case PS_SAVE_SET: |
| 124 | case PS_SNOOZE: |
| 125 | break; |
| 126 | case PS_CONF_WAIT: |
| 127 | atomic_set(&priv->psstatus.confirm_wait,0); |
| 128 | break; |
| 129 | case PS_NONE: |
| 130 | default: |
| 131 | hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST); |
| 132 | break; |
| 133 | } |
| 134 | |
| 135 | } |
| 136 | else{ |
| 137 | switch(atomic_read(&priv->psstatus.status)){ |
| 138 | case PS_ACTIVE_SET: |
| 139 | case PS_WAKEUP: |
| 140 | case PS_SAVE_SET: |
| 141 | break; |
| 142 | case PS_CONF_WAIT: |
| 143 | atomic_set(&priv->psstatus.confirm_wait,0); |
| 144 | atomic_set(&priv->psstatus.status, PS_WAKEUP); |
| 145 | break; |
| 146 | case PS_SNOOZE: |
| 147 | ks_wlan_hw_power_save(priv); |
| 148 | break; |
| 149 | case PS_NONE: |
| 150 | default: |
| 151 | hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST); |
| 152 | break; |
| 153 | } |
| 154 | } |
| 155 | #endif |
| 156 | return rc; |
| 157 | } |
| 158 | |
| 159 | static |
| 160 | int get_current_ap(ks_wlan_private *priv, struct link_ap_info_t *ap_info) |
| 161 | { |
| 162 | struct local_ap_t *ap; |
| 163 | #if WIRELESS_EXT > 13 |
| 164 | union iwreq_data wrqu; |
| 165 | struct net_device *netdev=priv->net_dev; |
| 166 | #endif /* WIRELESS_EXT > 13 */ |
| 167 | int rc=0; |
| 168 | |
| 169 | DPRINTK(3,"\n"); |
| 170 | ap = &(priv->current_ap); |
| 171 | |
| 172 | if((priv->connect_status & CONNECT_STATUS_MASK)== DISCONNECT_STATUS){ |
| 173 | memset(ap,0,sizeof(struct local_ap_t)); |
| 174 | return 1; |
| 175 | } |
| 176 | |
| 177 | /* bssid */ |
| 178 | memcpy(&(ap->bssid[0]),&(ap_info->bssid[0]),ETH_ALEN); |
| 179 | /* essid */ |
| 180 | memcpy(&(ap->ssid.body[0]),&(priv->reg.ssid.body[0]),priv->reg.ssid.size); |
| 181 | ap->ssid.size = priv->reg.ssid.size; |
| 182 | /* rate_set */ |
| 183 | memcpy(&(ap->rate_set.body[0]),&(ap_info->rate_set.body[0]),ap_info->rate_set.size); |
| 184 | ap->rate_set.size = ap_info->rate_set.size; |
| 185 | if(ap_info->ext_rate_set.size){ |
| 186 | /* rate_set */ |
| 187 | memcpy(&(ap->rate_set.body[ap->rate_set.size]), |
| 188 | &(ap_info->ext_rate_set.body[0]), |
| 189 | ap_info->ext_rate_set.size); |
| 190 | ap->rate_set.size += ap_info->ext_rate_set.size; |
| 191 | } |
| 192 | /* channel */ |
| 193 | ap->channel = ap_info->ds_parameter.channel; |
| 194 | /* rssi */ |
| 195 | ap->rssi = ap_info->rssi; |
| 196 | /* sq */ |
| 197 | ap->sq = ap_info->sq; |
| 198 | /* noise */ |
| 199 | ap->noise = ap_info->noise; |
| 200 | /* capability */ |
| 201 | ap->capability = ap_info->capability; |
| 202 | /* rsn */ |
| 203 | if((ap_info->rsn_mode & RSN_MODE_WPA2) && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)){ |
| 204 | ap->rsn_ie.id = 0x30; |
| 205 | if(ap_info->rsn.size <= RSN_IE_BODY_MAX){ |
| 206 | ap->rsn_ie.size = ap_info->rsn.size; |
| 207 | memcpy(&(ap->rsn_ie.body[0]),&(ap_info->rsn.body[0]),ap_info->rsn.size); |
| 208 | } |
| 209 | else{ |
| 210 | ap->rsn_ie.size = RSN_IE_BODY_MAX; |
| 211 | memcpy(&(ap->rsn_ie.body[0]),&(ap_info->rsn.body[0]),RSN_IE_BODY_MAX); |
| 212 | } |
| 213 | } |
| 214 | else if((ap_info->rsn_mode & RSN_MODE_WPA) && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA)){ |
| 215 | ap->wpa_ie.id = 0xdd; |
| 216 | if(ap_info->rsn.size <= RSN_IE_BODY_MAX){ |
| 217 | ap->wpa_ie.size = ap_info->rsn.size; |
| 218 | memcpy(&(ap->wpa_ie.body[0]),&(ap_info->rsn.body[0]),ap_info->rsn.size); |
| 219 | } |
| 220 | else{ |
| 221 | ap->wpa_ie.size = RSN_IE_BODY_MAX; |
| 222 | memcpy(&(ap->wpa_ie.body[0]),&(ap_info->rsn.body[0]),RSN_IE_BODY_MAX); |
| 223 | } |
| 224 | } |
| 225 | else{ |
| 226 | ap->rsn_ie.id = 0; |
| 227 | ap->rsn_ie.size = 0; |
| 228 | ap->wpa_ie.id = 0; |
| 229 | ap->wpa_ie.size = 0; |
| 230 | } |
| 231 | |
| 232 | #if WIRELESS_EXT > 13 |
| 233 | wrqu.data.length = 0; |
| 234 | wrqu.data.flags = 0; |
| 235 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
| 236 | if((priv->connect_status & CONNECT_STATUS_MASK)==CONNECT_STATUS){ |
| 237 | memcpy(wrqu.ap_addr.sa_data, |
| 238 | &(priv->current_ap.bssid[0]), ETH_ALEN); |
| 239 | DPRINTK(3,"IWEVENT: connect bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", |
| 240 | (unsigned char)wrqu.ap_addr.sa_data[0],(unsigned char)wrqu.ap_addr.sa_data[1], |
| 241 | (unsigned char)wrqu.ap_addr.sa_data[2],(unsigned char)wrqu.ap_addr.sa_data[3], |
| 242 | (unsigned char)wrqu.ap_addr.sa_data[4],(unsigned char)wrqu.ap_addr.sa_data[5]); |
| 243 | wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); |
| 244 | } |
| 245 | #endif |
| 246 | DPRINTK(4,"\n Link AP\n"); |
| 247 | DPRINTK(4," bssid=%02X:%02X:%02X:%02X:%02X:%02X\n \ |
| 248 | essid=%s\n rate_set=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n channel=%d\n \ |
| 249 | rssi=%d\n sq=%d\n capability=%04X\n", |
| 250 | ap->bssid[0],ap->bssid[1],ap->bssid[2],ap->bssid[3],ap->bssid[4], |
| 251 | ap->bssid[5],&(ap->ssid.body[0]),ap->rate_set.body[0],ap->rate_set.body[1], |
| 252 | ap->rate_set.body[2],ap->rate_set.body[3],ap->rate_set.body[4], |
| 253 | ap->rate_set.body[5],ap->rate_set.body[6],ap->rate_set.body[7], |
| 254 | ap->channel,ap->rssi,ap->sq,ap->capability); |
| 255 | DPRINTK(4,"\n Link AP\n rsn.mode=%d\n rsn.size=%d\n", |
| 256 | ap_info->rsn_mode,ap_info->rsn.size); |
| 257 | DPRINTK(4,"\n ext_rate_set_size=%d\n rate_set_size=%d\n", |
| 258 | ap_info->ext_rate_set.size,ap_info->rate_set.size); |
| 259 | |
| 260 | |
| 261 | return rc; |
| 262 | } |
| 263 | |
| 264 | static |
| 265 | int get_ap_information(ks_wlan_private *priv, struct ap_info_t *ap_info, struct local_ap_t *ap) |
| 266 | { |
| 267 | unsigned char *bp; |
| 268 | int bsize,offset; |
| 269 | int rc=0; |
| 270 | |
| 271 | DPRINTK(3,"\n"); |
| 272 | memset(ap,0,sizeof(struct local_ap_t)); |
| 273 | |
| 274 | /* bssid */ |
| 275 | memcpy(&(ap->bssid[0]),&(ap_info->bssid[0]),ETH_ALEN); |
| 276 | /* rssi */ |
| 277 | ap->rssi = ap_info->rssi; |
| 278 | /* sq */ |
| 279 | ap->sq = ap_info->sq; |
| 280 | /* noise */ |
| 281 | ap->noise = ap_info->noise; |
| 282 | /* capability */ |
| 283 | ap->capability = ap_info->capability; |
| 284 | /* channel */ |
| 285 | ap->channel = ap_info->ch_info; |
| 286 | |
| 287 | bp = &(ap_info->body[0]); |
| 288 | bsize = ap_info->body_size; |
| 289 | offset = 0; |
| 290 | |
| 291 | while(bsize > offset){ |
| 292 | /* DPRINTK(4, "Element ID=%d \n",*bp); */ |
| 293 | switch(*bp){ |
| 294 | case 0: /* ssid */ |
| 295 | if(*(bp+1) <= SSID_MAX_SIZE){ |
| 296 | ap->ssid.size = *(bp+1); |
| 297 | } |
| 298 | else { |
| 299 | DPRINTK(1, "size over :: ssid size=%d \n",*(bp+1)); |
| 300 | ap->ssid.size = SSID_MAX_SIZE; |
| 301 | } |
| 302 | memcpy(&(ap->ssid.body[0]),bp+2,ap->ssid.size); |
| 303 | break; |
| 304 | case 1: /* rate */ |
| 305 | case 50: /* ext rate */ |
| 306 | if((*(bp+1) + ap->rate_set.size) <= RATE_SET_MAX_SIZE){ |
| 307 | memcpy(&(ap->rate_set.body[ap->rate_set.size]),bp+2,*(bp+1)); |
| 308 | ap->rate_set.size += *(bp+1); |
| 309 | } |
| 310 | else{ |
| 311 | DPRINTK(1, "size over :: rate size=%d \n", |
| 312 | (*(bp+1) + ap->rate_set.size)); |
| 313 | memcpy(&(ap->rate_set.body[ap->rate_set.size]),bp+2, |
| 314 | RATE_SET_MAX_SIZE - ap->rate_set.size); |
| 315 | ap->rate_set.size += (RATE_SET_MAX_SIZE - ap->rate_set.size); |
| 316 | } |
| 317 | break; |
| 318 | case 3: /* DS parameter */ |
| 319 | break; |
| 320 | case 48: /* RSN(WPA2) */ |
| 321 | ap->rsn_ie.id = *bp; |
| 322 | if(*(bp+1) <= RSN_IE_BODY_MAX){ |
| 323 | ap->rsn_ie.size = *(bp+1); |
| 324 | }else{ |
| 325 | DPRINTK(1, "size over :: rsn size=%d \n",*(bp+1)); |
| 326 | ap->rsn_ie.size = RSN_IE_BODY_MAX; |
| 327 | } |
| 328 | memcpy(&(ap->rsn_ie.body[0]),bp+2,ap->rsn_ie.size); |
| 329 | break; |
| 330 | case 221: /* WPA */ |
| 331 | if(!memcmp(bp+2, "\x00\x50\xf2\x01", 4)){ /* WPA OUI check */ |
| 332 | ap->wpa_ie.id = *bp; |
| 333 | if(*(bp+1) <= RSN_IE_BODY_MAX){ |
| 334 | ap->wpa_ie.size = *(bp+1); |
| 335 | }else{ |
| 336 | DPRINTK(1, "size over :: wpa size=%d \n",*(bp+1)); |
| 337 | ap->wpa_ie.size = RSN_IE_BODY_MAX; |
| 338 | } |
| 339 | memcpy(&(ap->wpa_ie.body[0]),bp+2,ap->wpa_ie.size); |
| 340 | } |
| 341 | break; |
| 342 | |
| 343 | case 2: /* FH parameter */ |
| 344 | case 4: /* CF parameter */ |
| 345 | case 5: /* TIM */ |
| 346 | case 6: /* IBSS parameter */ |
| 347 | case 7: /* Country */ |
| 348 | case 42: /* ERP information */ |
| 349 | case 47: /* Reserve ID 47 Broadcom AP */ |
| 350 | break; |
| 351 | default: |
| 352 | DPRINTK(4, "unknown Element ID=%d \n",*bp); |
| 353 | break; |
| 354 | } |
| 355 | offset += 2; /* id & size field */ |
| 356 | offset += *(bp+1); /* +size offset */ |
| 357 | bp += (*(bp+1) + 2); /* pointer update */ |
| 358 | } |
| 359 | |
| 360 | return rc; |
| 361 | } |
| 362 | |
| 363 | static |
| 364 | void hostif_data_indication(ks_wlan_private *priv) |
| 365 | { |
| 366 | unsigned int rx_ind_size; /* indicate data size */ |
| 367 | struct sk_buff *skb; |
| 368 | unsigned short auth_type; |
| 369 | unsigned char temp[256]; |
| 370 | |
| 371 | unsigned char RecvMIC[8]; |
| 372 | char buf[128]; |
| 373 | struct ether_hdr *eth_hdr; |
| 374 | unsigned short eth_proto; |
| 375 | unsigned long now; |
| 376 | struct mic_failure_t *mic_failure; |
| 377 | struct ieee802_1x_hdr *aa1x_hdr; |
| 378 | struct wpa_eapol_key *eap_key; |
| 379 | struct michel_mic_t michel_mic; |
| 380 | #if WIRELESS_EXT > 14 |
| 381 | union iwreq_data wrqu; |
| 382 | #endif /* WIRELESS_EXT > 14 */ |
| 383 | |
| 384 | DPRINTK(3,"\n"); |
| 385 | |
| 386 | /* min length check */ |
| 387 | if (priv->rx_size <= ETH_HLEN) { |
| 388 | DPRINTK(3,"rx_size = %d\n", priv->rx_size); |
| 389 | priv->nstats.rx_errors++; |
| 390 | return; |
| 391 | } |
| 392 | |
| 393 | auth_type = get_WORD(priv); /* AuthType */ |
| 394 | get_WORD(priv); /* Reserve Area */ |
| 395 | |
| 396 | eth_hdr = (struct ether_hdr *)(priv->rxp); |
| 397 | eth_proto = ntohs(eth_hdr->h_proto); |
| 398 | DPRINTK(3,"ether protocol = %04X\n", eth_proto); |
| 399 | |
| 400 | /* source address check */ |
| 401 | if (!memcmp(&priv->eth_addr[0],eth_hdr->h_source, ETH_ALEN)){ |
| 402 | DPRINTK(1, "invalid : source is own mac address !!\n"); |
| 403 | DPRINTK(1, "eth_hdrernet->h_dest=%02X:%02X:%02X:%02X:%02X:%02X\n", |
| 404 | eth_hdr->h_source[0],eth_hdr->h_source[1],eth_hdr->h_source[2], |
| 405 | eth_hdr->h_source[3],eth_hdr->h_source[4],eth_hdr->h_source[5]); |
| 406 | priv->nstats.rx_errors++; |
| 407 | return; |
| 408 | } |
| 409 | |
| 410 | /* for WPA */ |
| 411 | if (auth_type != TYPE_DATA && priv->wpa.rsn_enabled){ |
| 412 | if(memcmp(ð_hdr->h_source[0],&priv->eth_addr[0],ETH_ALEN)){ /* source address check */ |
| 413 | if (eth_hdr->h_dest_snap != eth_hdr->h_source_snap){ |
| 414 | DPRINTK(1,"invalid data format\n"); |
| 415 | priv->nstats.rx_errors++; |
| 416 | return; |
| 417 | } |
| 418 | if(((auth_type==TYPE_PMK1 && priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP)|| |
| 419 | (auth_type==TYPE_GMK1 && priv->wpa.group_suite == IW_AUTH_CIPHER_TKIP)|| |
| 420 | (auth_type==TYPE_GMK2 && priv->wpa.group_suite == IW_AUTH_CIPHER_TKIP)) |
| 421 | && priv->wpa.key[auth_type-1].key_len){ |
| 422 | DPRINTK(4,"TKIP: protocol=%04X: size=%u\n", eth_proto, priv->rx_size); |
| 423 | /* MIC save */ |
| 424 | memcpy(&RecvMIC[0], (priv->rxp)+((priv->rx_size)-8), 8); |
| 425 | priv->rx_size = priv->rx_size - 8; |
| 426 | if(auth_type > 0 && auth_type < 4){ /* auth_type check */ |
| 427 | MichaelMICFunction(&michel_mic, |
| 428 | (uint8_t*)priv->wpa.key[auth_type-1].rx_mic_key, |
| 429 | (uint8_t*)priv->rxp, |
| 430 | (int)priv->rx_size, |
| 431 | (uint8_t)0, /* priority */ |
| 432 | (uint8_t*)michel_mic.Result); |
| 433 | } |
| 434 | if(memcmp(michel_mic.Result, RecvMIC, 8)){ |
| 435 | now = jiffies; |
| 436 | mic_failure = &priv->wpa.mic_failure; |
| 437 | /* MIC FAILURE */ |
| 438 | if(mic_failure->last_failure_time && |
| 439 | (now - mic_failure->last_failure_time)/HZ >= 60){ |
| 440 | mic_failure->failure=0; |
| 441 | } |
| 442 | DPRINTK(4,"MIC FAILURE \n"); |
| 443 | if(mic_failure->failure==0){ |
| 444 | mic_failure->failure=1; |
| 445 | mic_failure->counter=0; |
| 446 | }else if(mic_failure->failure==1){ |
| 447 | mic_failure->failure=2; |
| 448 | mic_failure->counter = |
| 449 | (uint16_t)((now - mic_failure->last_failure_time)/HZ); |
| 450 | if(!mic_failure->counter) /* mic_failure counter value range 1-60 */ |
| 451 | mic_failure->counter = 1; |
| 452 | } |
| 453 | priv->wpa.mic_failure.last_failure_time = now; |
| 454 | #if WIRELESS_EXT > 14 |
| 455 | /* needed parameters: count, keyid, key type, TSC */ |
| 456 | sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" |
| 457 | "%02x:%02x:%02x:%02x:%02x:%02x)", |
| 458 | auth_type-1, eth_hdr->h_dest[0] & 0x01 ? "broad" : "uni", |
| 459 | eth_hdr->h_source[0],eth_hdr->h_source[1], |
| 460 | eth_hdr->h_source[2],eth_hdr->h_source[3], |
| 461 | eth_hdr->h_source[4],eth_hdr->h_source[5]); |
| 462 | memset(&wrqu, 0, sizeof(wrqu)); |
| 463 | wrqu.data.length = strlen(buf); |
| 464 | DPRINTK(4,"IWEVENT:MICHAELMICFAILURE\n"); |
| 465 | wireless_send_event(priv->net_dev, IWEVCUSTOM, &wrqu, buf); |
| 466 | #endif /* WIRELESS_EXT > 14 */ |
| 467 | return; |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | } |
| 472 | |
| 473 | if((priv->connect_status & FORCE_DISCONNECT)|| |
| 474 | priv->wpa.mic_failure.failure==2){ |
| 475 | return; |
| 476 | } |
| 477 | |
| 478 | /* check 13th byte at rx data */ |
| 479 | switch (*(priv->rxp+12)) { |
| 480 | case 0xAA: /* SNAP */ |
| 481 | rx_ind_size = priv->rx_size - 6; |
| 482 | skb = dev_alloc_skb (rx_ind_size); |
| 483 | DPRINTK(4,"SNAP, rx_ind_size = %d\n", rx_ind_size); |
| 484 | |
| 485 | if(skb) { |
| 486 | memcpy(skb_put(skb,12),priv->rxp,12); /* 8802/FDDI MAC copy */ |
| 487 | /* (SNAP+UI..) skip */ |
| 488 | memcpy(skb_put(skb,rx_ind_size-12),priv->rxp+18,rx_ind_size-12); /* copy after Type */ |
| 489 | |
| 490 | aa1x_hdr=(struct ieee802_1x_hdr *)(priv->rxp+20); |
| 491 | if(aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && priv->wpa.rsn_enabled){ |
| 492 | eap_key = (struct wpa_eapol_key *)(aa1x_hdr+1); |
| 493 | atomic_set(&priv->psstatus.snooze_guard, 1); |
| 494 | } |
| 495 | |
| 496 | /* rx indication */ |
| 497 | skb->dev = priv->net_dev; |
| 498 | skb->protocol = eth_type_trans (skb, skb->dev); |
| 499 | priv->nstats.rx_packets++; |
| 500 | priv->nstats.rx_bytes += rx_ind_size; |
| 501 | skb->dev->last_rx = jiffies; |
| 502 | netif_rx (skb); |
| 503 | } else { |
| 504 | printk (KERN_WARNING"%s: Memory squeeze, dropping packet.\n",skb->dev->name); |
| 505 | priv->nstats.rx_dropped++; |
| 506 | } |
| 507 | break; |
| 508 | case 0xF0: /* NETBEUI/NetBIOS */ |
| 509 | rx_ind_size = (priv->rx_size + 2); |
| 510 | skb = dev_alloc_skb (rx_ind_size); |
| 511 | DPRINTK(3,"NETBEUI/NetBIOS rx_ind_size=%d\n", rx_ind_size); |
| 512 | |
| 513 | if(skb) { |
| 514 | memcpy(skb_put(skb,12),priv->rxp,12); /* 8802/FDDI MAC copy */ |
| 515 | |
| 516 | temp[0] = (((rx_ind_size-12) >> 8) & 0xff); /* NETBEUI size add */ |
| 517 | temp[1] = ((rx_ind_size-12) & 0xff); |
| 518 | memcpy(skb_put(skb,2),temp,2); |
| 519 | |
| 520 | memcpy(skb_put(skb,rx_ind_size-14),priv->rxp+12,rx_ind_size-14); /* copy after Type */ |
| 521 | |
| 522 | aa1x_hdr=(struct ieee802_1x_hdr *)(priv->rxp+14); |
| 523 | if(aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && priv->wpa.rsn_enabled){ |
| 524 | eap_key = (struct wpa_eapol_key *)(aa1x_hdr+1); |
| 525 | atomic_set(&priv->psstatus.snooze_guard, 1); |
| 526 | } |
| 527 | |
| 528 | /* rx indication */ |
| 529 | skb->dev = priv->net_dev; |
| 530 | skb->protocol = eth_type_trans (skb, skb->dev); |
| 531 | priv->nstats.rx_packets++; |
| 532 | priv->nstats.rx_bytes += rx_ind_size; |
| 533 | skb->dev->last_rx = jiffies; |
| 534 | netif_rx (skb); |
| 535 | } else { |
| 536 | printk (KERN_WARNING"%s: Memory squeeze, dropping packet.\n",skb->dev->name); |
| 537 | priv->nstats.rx_dropped++; |
| 538 | } |
| 539 | break; |
| 540 | default: /* other rx data */ |
| 541 | DPRINTK(2,"invalid data format\n"); |
| 542 | priv->nstats.rx_errors++; |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | static |
| 547 | void hostif_mib_get_confirm(ks_wlan_private *priv) |
| 548 | { |
| 549 | struct net_device *dev=priv->net_dev; |
| 550 | uint32_t mib_status; |
| 551 | uint32_t mib_attribute; |
| 552 | uint16_t mib_val_size; |
| 553 | uint16_t mib_val_type; |
| 554 | |
| 555 | DPRINTK(3, "\n"); |
| 556 | |
| 557 | mib_status = get_DWORD(priv); /* MIB status */ |
| 558 | mib_attribute = get_DWORD(priv); /* MIB atttibute */ |
| 559 | mib_val_size = get_WORD(priv); /* MIB value size */ |
| 560 | mib_val_type = get_WORD(priv); /* MIB value type */ |
| 561 | |
| 562 | if (mib_status != 0) { |
| 563 | /* in case of error */ |
| 564 | DPRINTK(1, "attribute=%08X, status=%08X\n", mib_attribute, mib_status); |
| 565 | return; |
| 566 | } |
| 567 | |
| 568 | switch (mib_attribute) { |
| 569 | case DOT11_MAC_ADDRESS: |
| 570 | /* MAC address */ |
| 571 | DPRINTK(3," mib_attribute=DOT11_MAC_ADDRESS\n"); |
| 572 | hostif_sme_enqueue(priv, SME_GET_MAC_ADDRESS); |
| 573 | memcpy(priv->eth_addr, priv->rxp, ETH_ALEN); |
| 574 | priv->mac_address_valid = 1; |
| 575 | dev->dev_addr[0] = priv->eth_addr[0]; |
| 576 | dev->dev_addr[1] = priv->eth_addr[1]; |
| 577 | dev->dev_addr[2] = priv->eth_addr[2]; |
| 578 | dev->dev_addr[3] = priv->eth_addr[3]; |
| 579 | dev->dev_addr[4] = priv->eth_addr[4]; |
| 580 | dev->dev_addr[5] = priv->eth_addr[5]; |
| 581 | dev->dev_addr[6] = 0x00; |
| 582 | dev->dev_addr[7] = 0x00; |
| 583 | printk(KERN_INFO "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 584 | priv->eth_addr[0],priv->eth_addr[1],priv->eth_addr[2], |
| 585 | priv->eth_addr[3],priv->eth_addr[4],priv->eth_addr[5]); |
| 586 | break; |
| 587 | case DOT11_PRODUCT_VERSION: |
| 588 | /* firmware version */ |
| 589 | DPRINTK(3," mib_attribute=DOT11_PRODUCT_VERSION\n"); |
| 590 | priv->version_size = priv->rx_size; |
| 591 | memcpy(priv->firmware_version, priv->rxp, priv->rx_size); |
| 592 | priv->firmware_version[priv->rx_size] = '\0'; |
| 593 | printk(KERN_INFO "ks_wlan: firmware ver. = %s\n",priv->firmware_version); |
| 594 | hostif_sme_enqueue(priv, SME_GET_PRODUCT_VERSION); |
| 595 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
| 596 | complete(&priv->confirm_wait); |
| 597 | break; |
| 598 | case LOCAL_GAIN: |
| 599 | memcpy(&priv->gain, priv->rxp, sizeof(priv->gain)); |
| 600 | DPRINTK(3, "TxMode=%d, RxMode=%d, TxGain=%d, RxGain=%d\n", |
| 601 | priv->gain.TxMode, priv->gain.RxMode, priv->gain.TxGain, priv->gain.RxGain); |
| 602 | break; |
| 603 | case LOCAL_EEPROM_SUM: |
| 604 | memcpy(&priv->eeprom_sum, priv->rxp, sizeof(priv->eeprom_sum)); |
| 605 | DPRINTK(1, "eeprom_sum.type=%x, eeprom_sum.result=%x\n", priv->eeprom_sum.type, priv->eeprom_sum.result); |
| 606 | if(priv->eeprom_sum.type == 0){ |
| 607 | priv->eeprom_checksum = EEPROM_CHECKSUM_NONE; |
| 608 | }else if(priv->eeprom_sum.type == 1){ |
| 609 | if(priv->eeprom_sum.result == 0){ |
| 610 | priv->eeprom_checksum = EEPROM_NG; |
| 611 | printk("LOCAL_EEPROM_SUM NG\n"); |
| 612 | }else if(priv->eeprom_sum.result == 1){ |
| 613 | priv->eeprom_checksum = EEPROM_OK; |
| 614 | } |
| 615 | }else{ |
| 616 | printk("LOCAL_EEPROM_SUM error!\n"); |
| 617 | } |
| 618 | break; |
| 619 | default: |
| 620 | DPRINTK(1,"mib_attribute=%08x\n",(unsigned int)mib_attribute); |
| 621 | break; |
| 622 | } |
| 623 | } |
| 624 | |
| 625 | static |
| 626 | void hostif_mib_set_confirm(ks_wlan_private *priv) |
| 627 | { |
| 628 | uint32_t mib_status; /* +04 MIB Status */ |
| 629 | uint32_t mib_attribute; /* +08 MIB attribute */ |
| 630 | |
| 631 | DPRINTK(3,"\n"); |
| 632 | |
| 633 | mib_status = get_DWORD(priv); /* MIB Status */ |
| 634 | mib_attribute = get_DWORD(priv); /* MIB attribute */ |
| 635 | |
| 636 | if (mib_status != 0) { |
| 637 | /* in case of error */ |
| 638 | DPRINTK(1, "error :: attribute=%08X, status=%08X\n", mib_attribute, mib_status); |
| 639 | } |
| 640 | |
| 641 | switch (mib_attribute) { |
| 642 | case DOT11_RTS_THRESHOLD: |
| 643 | hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_CONFIRM); |
| 644 | break; |
| 645 | case DOT11_FRAGMENTATION_THRESHOLD: |
| 646 | hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_CONFIRM); |
| 647 | break; |
| 648 | case DOT11_WEP_DEFAULT_KEY_ID: |
| 649 | if(!priv->wpa.wpa_enabled) |
| 650 | hostif_sme_enqueue(priv, SME_WEP_INDEX_CONFIRM); |
| 651 | break; |
| 652 | case DOT11_WEP_DEFAULT_KEY_VALUE1: |
| 653 | DPRINTK(2,"DOT11_WEP_DEFAULT_KEY_VALUE1:mib_status=%d\n",(int)mib_status); |
| 654 | if(priv->wpa.rsn_enabled) |
| 655 | hostif_sme_enqueue(priv, SME_SET_PMK_TSC); |
| 656 | else |
| 657 | hostif_sme_enqueue(priv, SME_WEP_KEY1_CONFIRM); |
| 658 | break; |
| 659 | case DOT11_WEP_DEFAULT_KEY_VALUE2: |
| 660 | DPRINTK(2,"DOT11_WEP_DEFAULT_KEY_VALUE2:mib_status=%d\n",(int)mib_status); |
| 661 | if(priv->wpa.rsn_enabled) |
| 662 | hostif_sme_enqueue(priv, SME_SET_GMK1_TSC); |
| 663 | else |
| 664 | hostif_sme_enqueue(priv, SME_WEP_KEY2_CONFIRM); |
| 665 | break; |
| 666 | case DOT11_WEP_DEFAULT_KEY_VALUE3: |
| 667 | DPRINTK(2,"DOT11_WEP_DEFAULT_KEY_VALUE3:mib_status=%d\n",(int)mib_status); |
| 668 | if(priv->wpa.rsn_enabled) |
| 669 | hostif_sme_enqueue(priv, SME_SET_GMK2_TSC); |
| 670 | else |
| 671 | hostif_sme_enqueue(priv, SME_WEP_KEY3_CONFIRM); |
| 672 | break; |
| 673 | case DOT11_WEP_DEFAULT_KEY_VALUE4: |
| 674 | DPRINTK(2,"DOT11_WEP_DEFAULT_KEY_VALUE4:mib_status=%d\n",(int)mib_status); |
| 675 | if(!priv->wpa.rsn_enabled) |
| 676 | hostif_sme_enqueue(priv, SME_WEP_KEY4_CONFIRM); |
| 677 | break; |
| 678 | case DOT11_PRIVACY_INVOKED: |
| 679 | if(!priv->wpa.rsn_enabled) |
| 680 | hostif_sme_enqueue(priv, SME_WEP_FLAG_CONFIRM); |
| 681 | break; |
| 682 | case DOT11_RSN_ENABLED: |
| 683 | DPRINTK(2,"DOT11_RSN_ENABLED:mib_status=%d\n",(int)mib_status); |
| 684 | hostif_sme_enqueue(priv, SME_RSN_ENABLED_CONFIRM); |
| 685 | break; |
| 686 | case LOCAL_RSN_MODE: |
| 687 | hostif_sme_enqueue(priv, SME_RSN_MODE_CONFIRM); |
| 688 | break; |
| 689 | case LOCAL_MULTICAST_ADDRESS: |
| 690 | hostif_sme_enqueue(priv, SME_MULTICAST_REQUEST); |
| 691 | break; |
| 692 | case LOCAL_MULTICAST_FILTER: |
| 693 | hostif_sme_enqueue(priv, SME_MULTICAST_CONFIRM); |
| 694 | break; |
| 695 | case LOCAL_CURRENTADDRESS: |
| 696 | priv->mac_address_valid = 1; |
| 697 | break; |
| 698 | case DOT11_RSN_CONFIG_MULTICAST_CIPHER: |
| 699 | DPRINTK(2,"DOT11_RSN_CONFIG_MULTICAST_CIPHER:mib_status=%d\n",(int)mib_status); |
| 700 | hostif_sme_enqueue(priv, SME_RSN_MCAST_CONFIRM); |
| 701 | break; |
| 702 | case DOT11_RSN_CONFIG_UNICAST_CIPHER: |
| 703 | DPRINTK(2,"DOT11_RSN_CONFIG_UNICAST_CIPHER:mib_status=%d\n",(int)mib_status); |
| 704 | hostif_sme_enqueue(priv, SME_RSN_UCAST_CONFIRM); |
| 705 | break; |
| 706 | case DOT11_RSN_CONFIG_AUTH_SUITE: |
| 707 | DPRINTK(2,"DOT11_RSN_CONFIG_AUTH_SUITE:mib_status=%d\n",(int)mib_status); |
| 708 | hostif_sme_enqueue(priv, SME_RSN_AUTH_CONFIRM); |
| 709 | break; |
| 710 | case DOT11_PMK_TSC: |
| 711 | DPRINTK(2,"DOT11_PMK_TSC:mib_status=%d\n",(int)mib_status); |
| 712 | break; |
| 713 | case DOT11_GMK1_TSC: |
| 714 | DPRINTK(2,"DOT11_GMK1_TSC:mib_status=%d\n",(int)mib_status); |
| 715 | if(atomic_read(&priv->psstatus.snooze_guard)){ |
| 716 | atomic_set(&priv->psstatus.snooze_guard, 0); |
| 717 | } |
| 718 | break; |
| 719 | case DOT11_GMK2_TSC: |
| 720 | DPRINTK(2,"DOT11_GMK2_TSC:mib_status=%d\n",(int)mib_status); |
| 721 | if(atomic_read(&priv->psstatus.snooze_guard)){ |
| 722 | atomic_set(&priv->psstatus.snooze_guard, 0); |
| 723 | } |
| 724 | break; |
| 725 | case LOCAL_PMK: |
| 726 | DPRINTK(2,"LOCAL_PMK:mib_status=%d\n",(int)mib_status); |
| 727 | break; |
| 728 | case LOCAL_GAIN: |
| 729 | DPRINTK(2,"LOCAL_GAIN:mib_status=%d\n",(int)mib_status); |
| 730 | break; |
| 731 | #ifdef WPS |
| 732 | case LOCAL_WPS_ENABLE: |
| 733 | DPRINTK(2,"LOCAL_WPS_ENABLE:mib_status=%d\n",(int)mib_status); |
| 734 | break; |
| 735 | case LOCAL_WPS_PROBE_REQ: |
| 736 | DPRINTK(2,"LOCAL_WPS_PROBE_REQ:mib_status=%d\n",(int)mib_status); |
| 737 | break; |
| 738 | #endif /* WPS */ |
| 739 | case LOCAL_REGION: |
| 740 | DPRINTK(2,"LOCAL_REGION:mib_status=%d\n",(int)mib_status); |
| 741 | default : |
| 742 | break; |
| 743 | } |
| 744 | } |
| 745 | |
| 746 | static |
| 747 | void hostif_power_mngmt_confirm(ks_wlan_private *priv) |
| 748 | { |
| 749 | DPRINTK(3,"\n"); |
| 750 | |
| 751 | if(priv->reg.powermgt > POWMGT_ACTIVE_MODE && |
| 752 | priv->reg.operation_mode == MODE_INFRASTRUCTURE){ |
| 753 | #if !defined(_SDIO_) |
| 754 | atomic_set(&priv->psstatus.status,PS_SAVE_SET); |
| 755 | #endif |
| 756 | atomic_set(&priv->psstatus.confirm_wait, 0); |
| 757 | priv->dev_state = DEVICE_STATE_SLEEP; |
| 758 | ks_wlan_hw_power_save(priv); |
| 759 | }else{ |
| 760 | priv->dev_state = DEVICE_STATE_READY; |
| 761 | #if !defined(_SDIO_) |
| 762 | atomic_set(&priv->psstatus.status,PS_ACTIVE_SET); |
| 763 | #endif |
| 764 | } |
| 765 | |
| 766 | } |
| 767 | |
| 768 | static |
| 769 | void hostif_sleep_confirm(ks_wlan_private *priv) |
| 770 | { |
| 771 | DPRINTK(3,"\n"); |
| 772 | |
| 773 | atomic_set(&priv->sleepstatus.doze_request,1); |
| 774 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 775 | } |
| 776 | |
| 777 | static |
| 778 | void hostif_start_confirm(ks_wlan_private *priv) |
| 779 | { |
| 780 | #ifdef WPS |
| 781 | union iwreq_data wrqu; |
| 782 | wrqu.data.length = 0; |
| 783 | wrqu.data.flags = 0; |
| 784 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
| 785 | if((priv->connect_status & CONNECT_STATUS_MASK)== CONNECT_STATUS){ |
| 786 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); |
| 787 | DPRINTK(3,"IWEVENT: disconnect\n"); |
| 788 | wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); |
| 789 | } |
| 790 | #endif |
| 791 | DPRINTK(3," scan_ind_count=%d\n",priv->scan_ind_count); |
| 792 | hostif_sme_enqueue(priv, SME_START_CONFIRM); |
| 793 | } |
| 794 | |
| 795 | static |
| 796 | void hostif_connect_indication(ks_wlan_private *priv) |
| 797 | { |
| 798 | unsigned short connect_code; |
| 799 | unsigned int tmp=0; |
| 800 | unsigned int old_status=priv->connect_status; |
| 801 | struct net_device *netdev=priv->net_dev; |
| 802 | #if WIRELESS_EXT > 13 |
| 803 | union iwreq_data wrqu0; |
| 804 | #endif /* WIRELESS_EXT > 13 */ |
| 805 | connect_code = get_WORD(priv); |
| 806 | |
| 807 | switch(connect_code){ |
| 808 | case RESULT_CONNECT: /* connect */ |
| 809 | DPRINTK(3,"connect :: scan_ind_count=%d\n",priv->scan_ind_count); |
| 810 | if(!(priv->connect_status & FORCE_DISCONNECT)) |
| 811 | netif_carrier_on(netdev); |
| 812 | tmp = FORCE_DISCONNECT & priv->connect_status; |
| 813 | priv->connect_status = tmp + CONNECT_STATUS; |
| 814 | break; |
| 815 | case RESULT_DISCONNECT: /* disconnect */ |
| 816 | DPRINTK(3,"disconnect :: scan_ind_count=%d\n",priv->scan_ind_count); |
| 817 | netif_carrier_off(netdev); |
| 818 | tmp = FORCE_DISCONNECT & priv->connect_status; |
| 819 | priv->connect_status = tmp + DISCONNECT_STATUS; |
| 820 | break; |
| 821 | default: |
| 822 | DPRINTK(1,"unknown connect_code=%d :: scan_ind_count=%d\n", |
| 823 | connect_code,priv->scan_ind_count); |
| 824 | netif_carrier_off(netdev); |
| 825 | tmp = FORCE_DISCONNECT & priv->connect_status; |
| 826 | priv->connect_status = tmp + DISCONNECT_STATUS; |
| 827 | break; |
| 828 | } |
| 829 | |
| 830 | get_current_ap(priv, (struct link_ap_info_t *)priv->rxp); |
| 831 | if((priv->connect_status & CONNECT_STATUS_MASK)== CONNECT_STATUS && |
| 832 | (old_status & CONNECT_STATUS_MASK)==DISCONNECT_STATUS ){ |
| 833 | /* for power save */ |
| 834 | atomic_set(&priv->psstatus.snooze_guard, 0); |
| 835 | atomic_set(&priv->psstatus.confirm_wait,0); |
| 836 | #if !defined(_SDIO_) |
| 837 | atomic_set(&priv->psstatus.status, PS_NONE); |
| 838 | #endif |
| 839 | } |
| 840 | ks_wlan_do_power_save(priv); |
| 841 | |
| 842 | #if WIRELESS_EXT > 13 |
| 843 | wrqu0.data.length = 0; |
| 844 | wrqu0.data.flags = 0; |
| 845 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; |
| 846 | if((priv->connect_status & CONNECT_STATUS_MASK)== DISCONNECT_STATUS && |
| 847 | (old_status & CONNECT_STATUS_MASK)==CONNECT_STATUS ){ |
| 848 | memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); |
| 849 | DPRINTK(3,"IWEVENT: disconnect\n"); |
| 850 | DPRINTK(3,"disconnect :: scan_ind_count=%d\n",priv->scan_ind_count); |
| 851 | wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL); |
| 852 | } |
| 853 | #endif /* WIRELESS_EXT > 13 */ |
| 854 | priv->scan_ind_count=0; |
| 855 | } |
| 856 | |
| 857 | static |
| 858 | void hostif_scan_indication(ks_wlan_private *priv) |
| 859 | { |
| 860 | int i; |
| 861 | struct ap_info_t *ap_info; |
| 862 | |
| 863 | DPRINTK(3,"scan_ind_count = %d\n", priv->scan_ind_count); |
| 864 | ap_info = (struct ap_info_t *)(priv->rxp); |
| 865 | |
| 866 | if(priv->scan_ind_count!=0){ |
| 867 | for(i=0;i<priv->aplist.size;i++){ /* bssid check */ |
| 868 | if(!memcmp(&(ap_info->bssid[0]),&(priv->aplist.ap[i].bssid[0]),ETH_ALEN)){ |
| 869 | if(ap_info->frame_type == FRAME_TYPE_PROBE_RESP) |
| 870 | get_ap_information(priv,ap_info,&(priv->aplist.ap[i])); |
| 871 | return; |
| 872 | } |
| 873 | } |
| 874 | } |
| 875 | priv->scan_ind_count++; |
| 876 | if(priv->scan_ind_count < LOCAL_APLIST_MAX+1){ |
| 877 | DPRINTK(4," scan_ind_count=%d :: aplist.size=%d\n", priv->scan_ind_count, priv->aplist.size); |
| 878 | get_ap_information(priv,(struct ap_info_t *)(priv->rxp),&(priv->aplist.ap[priv->scan_ind_count-1])); |
| 879 | priv->aplist.size = priv->scan_ind_count; |
| 880 | } |
| 881 | else{ |
| 882 | DPRINTK(4," count over :: scan_ind_count=%d\n", priv->scan_ind_count); |
| 883 | } |
| 884 | |
| 885 | |
| 886 | } |
| 887 | |
| 888 | static |
| 889 | void hostif_stop_confirm(ks_wlan_private *priv) |
| 890 | { |
| 891 | unsigned int tmp=0; |
| 892 | unsigned int old_status=priv->connect_status; |
| 893 | struct net_device *netdev=priv->net_dev; |
| 894 | union iwreq_data wrqu0; |
| 895 | |
| 896 | DPRINTK(3,"\n"); |
| 897 | #ifdef _SDIO_ |
| 898 | if(priv->dev_state == DEVICE_STATE_SLEEP) |
| 899 | priv->dev_state = DEVICE_STATE_READY; |
| 900 | #endif |
| 901 | |
| 902 | /* disconnect indication */ |
| 903 | if( (priv->connect_status & CONNECT_STATUS_MASK)== CONNECT_STATUS){ |
| 904 | netif_carrier_off(netdev); |
| 905 | tmp = FORCE_DISCONNECT & priv->connect_status; |
| 906 | priv->connect_status = tmp | DISCONNECT_STATUS; |
| 907 | printk("IWEVENT: disconnect\n"); |
| 908 | |
| 909 | wrqu0.data.length = 0; |
| 910 | wrqu0.data.flags = 0; |
| 911 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; |
| 912 | if((priv->connect_status & CONNECT_STATUS_MASK)== DISCONNECT_STATUS && |
| 913 | (old_status & CONNECT_STATUS_MASK)==CONNECT_STATUS ){ |
| 914 | memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); |
| 915 | DPRINTK(3,"IWEVENT: disconnect\n"); |
| 916 | printk("IWEVENT: disconnect\n"); |
| 917 | DPRINTK(3,"disconnect :: scan_ind_count=%d\n",priv->scan_ind_count); |
| 918 | wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL); |
| 919 | } |
| 920 | priv->scan_ind_count=0; |
| 921 | } |
| 922 | |
| 923 | hostif_sme_enqueue(priv, SME_STOP_CONFIRM); |
| 924 | } |
| 925 | |
| 926 | static |
| 927 | void hostif_ps_adhoc_set_confirm(ks_wlan_private *priv) |
| 928 | { |
| 929 | DPRINTK(3,"\n"); |
| 930 | priv->infra_status = 0; /* infrastructure mode cancel */ |
| 931 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
| 932 | |
| 933 | } |
| 934 | |
| 935 | static |
| 936 | void hostif_infrastructure_set_confirm(ks_wlan_private *priv) |
| 937 | { |
| 938 | uint16_t result_code; |
| 939 | DPRINTK(3,"\n"); |
| 940 | result_code = get_WORD(priv); |
| 941 | DPRINTK(3,"result code = %d\n",result_code); |
| 942 | priv->infra_status = 1; /* infrastructure mode set */ |
| 943 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
| 944 | } |
| 945 | |
| 946 | static |
| 947 | void hostif_adhoc_set_confirm(ks_wlan_private *priv) |
| 948 | { |
| 949 | DPRINTK(3,"\n"); |
| 950 | priv->infra_status = 1; /* infrastructure mode set */ |
| 951 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
| 952 | } |
| 953 | |
| 954 | static |
| 955 | void hostif_associate_indication(ks_wlan_private *priv) |
| 956 | { |
| 957 | #if WIRELESS_EXT > 14 |
| 958 | struct association_request_t *assoc_req; |
| 959 | struct association_response_t *assoc_resp; |
| 960 | unsigned char *pb; |
| 961 | union iwreq_data wrqu; |
| 962 | char buf[IW_CUSTOM_MAX]; |
| 963 | char *pbuf = &buf[0]; |
| 964 | int i; |
| 965 | |
| 966 | static const char associnfo_leader0[] = "ASSOCINFO(ReqIEs="; |
| 967 | static const char associnfo_leader1[] = " RespIEs="; |
| 968 | |
| 969 | DPRINTK(3,"\n"); |
| 970 | assoc_req = (struct association_request_t *)(priv->rxp); |
| 971 | assoc_resp = (struct association_response_t *)(assoc_req+1); |
| 972 | pb = (unsigned char *)(assoc_resp+1); |
| 973 | |
| 974 | memset(&wrqu, 0, sizeof(wrqu)); |
| 975 | memcpy(pbuf,associnfo_leader0,sizeof(associnfo_leader0)-1); |
| 976 | wrqu.data.length += sizeof(associnfo_leader0)-1; |
| 977 | pbuf += sizeof(associnfo_leader0)-1; |
| 978 | |
| 979 | for (i = 0; i < assoc_req->reqIEs_size; i++) |
| 980 | pbuf += sprintf(pbuf, "%02x", *(pb+i)); |
| 981 | wrqu.data.length += (assoc_req->reqIEs_size)*2; |
| 982 | |
| 983 | memcpy(pbuf,associnfo_leader1,sizeof(associnfo_leader1)-1); |
| 984 | wrqu.data.length += sizeof(associnfo_leader1)-1; |
| 985 | pbuf += sizeof(associnfo_leader1)-1; |
| 986 | |
| 987 | pb += assoc_req->reqIEs_size; |
| 988 | for (i = 0; i < assoc_resp->respIEs_size; i++) |
| 989 | pbuf += sprintf(pbuf, "%02x", *(pb+i)); |
| 990 | wrqu.data.length += (assoc_resp->respIEs_size)*2; |
| 991 | |
| 992 | pbuf += sprintf(pbuf, ")"); |
| 993 | wrqu.data.length += 1; |
| 994 | |
| 995 | DPRINTK(3,"IWEVENT:ASSOCINFO\n"); |
| 996 | wireless_send_event(priv->net_dev, IWEVCUSTOM, &wrqu, buf); |
| 997 | #endif /* WIRELESS_EXT > 14 */ |
| 998 | } |
| 999 | |
| 1000 | static |
| 1001 | void hostif_bss_scan_confirm(ks_wlan_private *priv) |
| 1002 | { |
| 1003 | unsigned int result_code; |
| 1004 | #if WIRELESS_EXT > 13 |
| 1005 | struct net_device *dev = priv->net_dev; |
| 1006 | union iwreq_data wrqu; |
| 1007 | #endif /* WIRELESS_EXT > 13 */ |
| 1008 | result_code = get_DWORD(priv); |
| 1009 | DPRINTK(2,"result=%d :: scan_ind_count=%d\n", result_code, priv->scan_ind_count); |
| 1010 | |
| 1011 | priv->sme_i.sme_flag &= ~SME_AP_SCAN; |
| 1012 | hostif_sme_enqueue(priv, SME_BSS_SCAN_CONFIRM); |
| 1013 | |
| 1014 | #if WIRELESS_EXT > 13 |
| 1015 | wrqu.data.length = 0; |
| 1016 | wrqu.data.flags = 0; |
| 1017 | DPRINTK(3,"IWEVENT: SCAN CONFIRM\n"); |
| 1018 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); |
| 1019 | #endif /* WIRELESS_EXT > 13 */ |
| 1020 | priv->scan_ind_count=0; |
| 1021 | } |
| 1022 | |
| 1023 | static |
| 1024 | void hostif_phy_information_confirm(ks_wlan_private *priv) |
| 1025 | { |
| 1026 | struct iw_statistics *wstats = &priv->wstats; |
| 1027 | unsigned char rssi,signal,noise; |
| 1028 | unsigned char LinkSpeed; |
| 1029 | unsigned int TransmittedFrameCount, ReceivedFragmentCount; |
| 1030 | unsigned int FailedCount, FCSErrorCount; |
| 1031 | |
| 1032 | DPRINTK(3,"\n"); |
| 1033 | rssi = get_BYTE(priv); |
| 1034 | signal = get_BYTE(priv); |
| 1035 | noise = get_BYTE(priv); |
| 1036 | LinkSpeed = get_BYTE(priv); |
| 1037 | TransmittedFrameCount = get_DWORD(priv); |
| 1038 | ReceivedFragmentCount = get_DWORD(priv); |
| 1039 | FailedCount = get_DWORD(priv); |
| 1040 | FCSErrorCount = get_DWORD(priv); |
| 1041 | |
| 1042 | DPRINTK(4, "phyinfo confirm rssi=%d signal=%d\n", rssi, signal); |
| 1043 | priv->current_rate = (LinkSpeed & RATE_MASK); |
| 1044 | wstats->qual.qual = signal; |
| 1045 | wstats->qual.level = 256 - rssi; |
| 1046 | wstats->qual.noise = 0; /* invalid noise value */ |
| 1047 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
| 1048 | |
| 1049 | DPRINTK(3,"\n rssi=%u\n signal=%u\n LinkSpeed=%ux500Kbps\n \ |
| 1050 | TransmittedFrameCount=%u\n ReceivedFragmentCount=%u\n FailedCount=%u\n \ |
| 1051 | FCSErrorCount=%u\n", |
| 1052 | rssi,signal,LinkSpeed,TransmittedFrameCount, |
| 1053 | ReceivedFragmentCount,FailedCount,FCSErrorCount); |
| 1054 | |
| 1055 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
| 1056 | complete(&priv->confirm_wait); |
| 1057 | } |
| 1058 | |
| 1059 | static |
| 1060 | void hostif_mic_failure_confirm(ks_wlan_private *priv) |
| 1061 | { |
| 1062 | DPRINTK(3,"mic_failure=%u\n",priv->wpa.mic_failure.failure); |
| 1063 | hostif_sme_enqueue(priv, SME_MIC_FAILURE_CONFIRM); |
| 1064 | } |
| 1065 | |
| 1066 | |
| 1067 | static |
| 1068 | void hostif_event_check(ks_wlan_private *priv) |
| 1069 | { |
| 1070 | unsigned short event; |
| 1071 | |
| 1072 | DPRINTK(4, "\n"); |
| 1073 | event = get_WORD(priv); /* get event */ |
| 1074 | switch (event) { |
| 1075 | case HIF_DATA_IND: |
| 1076 | hostif_data_indication(priv); |
| 1077 | break; |
| 1078 | case HIF_MIB_GET_CONF: |
| 1079 | hostif_mib_get_confirm(priv); |
| 1080 | break; |
| 1081 | case HIF_MIB_SET_CONF: |
| 1082 | hostif_mib_set_confirm(priv); |
| 1083 | break; |
| 1084 | case HIF_POWERMGT_CONF: |
| 1085 | hostif_power_mngmt_confirm(priv); |
| 1086 | break; |
| 1087 | case HIF_SLEEP_CONF: |
| 1088 | hostif_sleep_confirm(priv); |
| 1089 | break; |
| 1090 | case HIF_START_CONF: |
| 1091 | hostif_start_confirm(priv); |
| 1092 | break; |
| 1093 | case HIF_CONNECT_IND: |
| 1094 | hostif_connect_indication(priv); |
| 1095 | break; |
| 1096 | case HIF_STOP_CONF: |
| 1097 | hostif_stop_confirm(priv); |
| 1098 | break; |
| 1099 | case HIF_PS_ADH_SET_CONF: |
| 1100 | hostif_ps_adhoc_set_confirm(priv); |
| 1101 | break; |
| 1102 | case HIF_INFRA_SET_CONF: |
| 1103 | case HIF_INFRA_SET2_CONF: |
| 1104 | hostif_infrastructure_set_confirm(priv); |
| 1105 | break; |
| 1106 | case HIF_ADH_SET_CONF: |
| 1107 | case HIF_ADH_SET2_CONF: |
| 1108 | hostif_adhoc_set_confirm(priv); |
| 1109 | break; |
| 1110 | case HIF_ASSOC_INFO_IND: |
| 1111 | hostif_associate_indication(priv); |
| 1112 | break; |
| 1113 | case HIF_MIC_FAILURE_CONF: |
| 1114 | hostif_mic_failure_confirm(priv); |
| 1115 | break; |
| 1116 | case HIF_SCAN_CONF: |
| 1117 | hostif_bss_scan_confirm(priv); |
| 1118 | break; |
| 1119 | case HIF_PHY_INFO_CONF: |
| 1120 | case HIF_PHY_INFO_IND: |
| 1121 | hostif_phy_information_confirm(priv); |
| 1122 | break; |
| 1123 | case HIF_SCAN_IND: |
| 1124 | hostif_scan_indication(priv); |
| 1125 | break; |
| 1126 | case HIF_AP_SET_CONF: |
| 1127 | default: |
| 1128 | //DPRINTK(1, "undefined event[%04X]\n", event); |
| 1129 | printk("undefined event[%04X]\n", event); |
| 1130 | /* wake_up_all(&priv->confirm_wait); */ |
| 1131 | complete(&priv->confirm_wait); |
| 1132 | break; |
| 1133 | } |
| 1134 | |
| 1135 | /* add event to hostt buffer */ |
| 1136 | priv->hostt.buff[priv->hostt.qtail] = event; |
| 1137 | priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE; |
| 1138 | } |
| 1139 | |
| 1140 | #define CHECK_ALINE(size) (size%4 ? (size+(4-(size%4))):size) |
| 1141 | |
| 1142 | int hostif_data_request(ks_wlan_private *priv, struct sk_buff *packet) |
| 1143 | { |
| 1144 | unsigned int packet_len=0; |
| 1145 | |
| 1146 | unsigned char *buffer=NULL; |
| 1147 | unsigned int length=0; |
| 1148 | struct hostif_data_request_t *pp; |
| 1149 | unsigned char *p; |
| 1150 | int result=0; |
| 1151 | unsigned short eth_proto; |
| 1152 | struct ether_hdr *eth_hdr; |
| 1153 | struct michel_mic_t michel_mic; |
| 1154 | unsigned short keyinfo=0; |
| 1155 | struct ieee802_1x_hdr *aa1x_hdr; |
| 1156 | struct wpa_eapol_key *eap_key; |
| 1157 | struct ethhdr *eth; |
| 1158 | |
| 1159 | packet_len = packet->len; |
| 1160 | if (packet_len > ETH_FRAME_LEN) { |
| 1161 | DPRINTK(1,"bad length packet_len=%d \n", packet_len); |
| 1162 | dev_kfree_skb(packet); |
| 1163 | return -1; |
| 1164 | } |
| 1165 | |
| 1166 | if(((priv->connect_status & CONNECT_STATUS_MASK)== DISCONNECT_STATUS) || |
| 1167 | (priv->connect_status & FORCE_DISCONNECT) || priv->wpa.mic_failure.stop){ |
| 1168 | DPRINTK(3," DISCONNECT\n"); |
| 1169 | if(netif_queue_stopped(priv->net_dev)) |
| 1170 | netif_wake_queue(priv->net_dev); |
| 1171 | if(packet) |
| 1172 | dev_kfree_skb(packet); |
| 1173 | |
| 1174 | return 0; |
| 1175 | } |
| 1176 | |
| 1177 | /* for PowerSave */ |
| 1178 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE){ /* power save wakeup */ |
| 1179 | if(!netif_queue_stopped(priv->net_dev)) |
| 1180 | netif_stop_queue(priv->net_dev); |
| 1181 | #if !defined(_SDIO_) |
| 1182 | schedule_work(&priv->ks_wlan_wakeup_task); |
| 1183 | #endif |
| 1184 | } |
| 1185 | |
| 1186 | DPRINTK(4, "skb_buff length=%d\n", packet_len); |
| 1187 | pp = (struct hostif_data_request_t *)kmalloc(hif_align_size(sizeof(*pp)+6+packet_len+8),KS_WLAN_MEM_FLAG ); |
| 1188 | |
| 1189 | if (pp==NULL) { |
| 1190 | DPRINTK(3, "allocate memory failed..\n"); |
| 1191 | dev_kfree_skb(packet); |
| 1192 | return -2; |
| 1193 | } |
| 1194 | |
| 1195 | p = (unsigned char *)pp->data; |
| 1196 | |
| 1197 | buffer = packet->data; |
| 1198 | length = packet->len; |
| 1199 | |
| 1200 | /* packet check */ |
| 1201 | eth = (struct ethhdr *)packet->data; |
| 1202 | if (memcmp(&priv->eth_addr[0],eth->h_source, ETH_ALEN)){ |
| 1203 | DPRINTK(1, "invalid mac address !!\n"); |
| 1204 | DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n", |
| 1205 | eth->h_source[0],eth->h_source[1],eth->h_source[2], |
| 1206 | eth->h_source[3],eth->h_source[4],eth->h_source[5]); |
| 1207 | return -3; |
| 1208 | } |
| 1209 | |
| 1210 | /* MAC address copy */ |
| 1211 | memcpy(p, buffer, 12); /* DST/SRC MAC address */ |
| 1212 | p += 12; |
| 1213 | buffer += 12; |
| 1214 | length -= 12; |
| 1215 | /* EtherType/Length check */ |
| 1216 | if (*(buffer+1) + (*buffer << 8) > 1500) { |
| 1217 | /* ProtocolEAP = *(buffer+1) + (*buffer << 8); */ |
| 1218 | /* DPRINTK(2, "Send [SNAP]Type %x\n",ProtocolEAP); */ |
| 1219 | /* SAP/CTL/OUI(6 byte) add */ |
| 1220 | *p++ = 0xAA; /* DSAP */ |
| 1221 | *p++ = 0xAA; /* SSAP */ |
| 1222 | *p++ = 0x03; /* CTL */ |
| 1223 | *p++ = 0x00; /* OUI ("000000") */ |
| 1224 | *p++ = 0x00; /* OUI ("000000") */ |
| 1225 | *p++ = 0x00; /* OUI ("000000") */ |
| 1226 | packet_len += 6; |
| 1227 | } else { |
| 1228 | DPRINTK(4,"DIX\n"); |
| 1229 | /* Length(2 byte) delete */ |
| 1230 | buffer += 2; |
| 1231 | length -= 2; |
| 1232 | packet_len -= 2; |
| 1233 | } |
| 1234 | |
| 1235 | /* pp->data copy */ |
| 1236 | memcpy(p, buffer, length); |
| 1237 | |
| 1238 | p += length; |
| 1239 | |
| 1240 | /* for WPA */ |
| 1241 | eth_hdr = (struct ether_hdr *)&pp->data[0]; |
| 1242 | eth_proto = ntohs(eth_hdr->h_proto); |
| 1243 | |
| 1244 | /* for MIC FAILUER REPORT check */ |
| 1245 | if(eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure>0){ |
| 1246 | aa1x_hdr=(struct ieee802_1x_hdr *)(eth_hdr+1); |
| 1247 | if(aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY){ |
| 1248 | eap_key = (struct wpa_eapol_key *)(aa1x_hdr+1); |
| 1249 | keyinfo=ntohs(eap_key->key_info); |
| 1250 | } |
| 1251 | } |
| 1252 | |
| 1253 | if (priv->wpa.rsn_enabled && priv->wpa.key[0].key_len){ |
| 1254 | if(eth_proto == ETHER_PROTOCOL_TYPE_EAP && !(priv->wpa.key[1].key_len) && |
| 1255 | !(priv->wpa.key[2].key_len) && !(priv->wpa.key[3].key_len)){ |
| 1256 | pp->auth_type = cpu_to_le16((uint16_t)TYPE_AUTH); /* no encryption */ |
| 1257 | } |
| 1258 | else{ |
| 1259 | if(priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP){ |
| 1260 | MichaelMICFunction( &michel_mic, |
| 1261 | (uint8_t*)priv->wpa.key[0].tx_mic_key, |
| 1262 | (uint8_t*)&pp->data[0], |
| 1263 | (int)packet_len, |
| 1264 | (uint8_t)0, /* priority */ |
| 1265 | (uint8_t*)michel_mic.Result ); |
| 1266 | memcpy(p, michel_mic.Result, 8); |
| 1267 | length += 8; |
| 1268 | packet_len += 8; |
| 1269 | p += 8; |
| 1270 | pp->auth_type = cpu_to_le16((uint16_t)TYPE_DATA); |
| 1271 | |
| 1272 | }else if(priv->wpa.pairwise_suite == IW_AUTH_CIPHER_CCMP){ |
| 1273 | pp->auth_type = cpu_to_le16((uint16_t)TYPE_DATA); |
| 1274 | } |
| 1275 | } |
| 1276 | } |
| 1277 | else{ |
| 1278 | if(eth_proto == ETHER_PROTOCOL_TYPE_EAP) |
| 1279 | pp->auth_type = cpu_to_le16((uint16_t)TYPE_AUTH); |
| 1280 | else |
| 1281 | pp->auth_type = cpu_to_le16((uint16_t)TYPE_DATA); |
| 1282 | } |
| 1283 | |
| 1284 | /* header value set */ |
| 1285 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size)+packet_len)); |
| 1286 | pp->header.event = cpu_to_le16((uint16_t)HIF_DATA_REQ); |
| 1287 | |
| 1288 | /* tx request */ |
| 1289 | result = ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + packet_len), |
| 1290 | (void *)send_packet_complete, (void *)priv, (void *)packet); |
| 1291 | |
| 1292 | /* MIC FAILUER REPORT check */ |
| 1293 | if(eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure>0){ |
| 1294 | if(keyinfo & WPA_KEY_INFO_ERROR && keyinfo & WPA_KEY_INFO_REQUEST){ |
| 1295 | DPRINTK(3," MIC ERROR Report SET : %04X\n", keyinfo); |
| 1296 | hostif_sme_enqueue(priv, SME_MIC_FAILURE_REQUEST); |
| 1297 | } |
| 1298 | if(priv->wpa.mic_failure.failure==2) |
| 1299 | priv->wpa.mic_failure.stop=1; |
| 1300 | } |
| 1301 | |
| 1302 | return result; |
| 1303 | } |
| 1304 | |
| 1305 | #if defined(_SPI_) |
| 1306 | #define ps_confirm_wait_inc(priv) |
| 1307 | #else |
| 1308 | #define ps_confirm_wait_inc(priv) do{if(atomic_read(&priv->psstatus.status) > PS_ACTIVE_SET){ \ |
| 1309 | atomic_inc(&priv->psstatus.confirm_wait); \ |
| 1310 | /* atomic_set(&priv->psstatus.status, PS_CONF_WAIT);*/ \ |
| 1311 | } }while(0) |
| 1312 | #endif |
| 1313 | |
| 1314 | static |
| 1315 | void hostif_mib_get_request( ks_wlan_private *priv, unsigned long mib_attribute) |
| 1316 | { |
| 1317 | struct hostif_mib_get_request_t *pp; |
| 1318 | |
| 1319 | DPRINTK(3, "\n"); |
| 1320 | |
| 1321 | /* make primitive */ |
| 1322 | pp = (struct hostif_mib_get_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1323 | if (pp==NULL) { |
| 1324 | DPRINTK(3,"allocate memory failed..\n"); |
| 1325 | return; |
| 1326 | } |
| 1327 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1328 | pp->header.event = cpu_to_le16((uint16_t)HIF_MIB_GET_REQ); |
| 1329 | pp->mib_attribute = cpu_to_le32((uint32_t)mib_attribute); |
| 1330 | |
| 1331 | /* send to device request */ |
| 1332 | ps_confirm_wait_inc(priv); |
| 1333 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1334 | } |
| 1335 | |
| 1336 | static |
| 1337 | void hostif_mib_set_request( ks_wlan_private *priv, unsigned long mib_attribute, |
| 1338 | unsigned short size, unsigned short type, |
| 1339 | void *vp ) |
| 1340 | { |
| 1341 | struct hostif_mib_set_request_t *pp; |
| 1342 | |
| 1343 | DPRINTK(3,"\n"); |
| 1344 | |
| 1345 | if (priv->dev_state < DEVICE_STATE_BOOT) { |
| 1346 | DPRINTK(3,"DeviceRemove\n"); |
| 1347 | return; |
| 1348 | } |
| 1349 | |
| 1350 | /* make primitive */ |
| 1351 | pp = (struct hostif_mib_set_request_t *)kmalloc(hif_align_size(sizeof(*pp)+size), KS_WLAN_MEM_FLAG ); |
| 1352 | if (pp==NULL) { |
| 1353 | DPRINTK(3, "allocate memory failed..\n"); |
| 1354 | return; |
| 1355 | } |
| 1356 | |
| 1357 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size)+size)); |
| 1358 | pp->header.event = cpu_to_le16((uint16_t)HIF_MIB_SET_REQ); |
| 1359 | pp->mib_attribute = cpu_to_le32((uint32_t)mib_attribute); |
| 1360 | pp->mib_value.size = cpu_to_le16((uint16_t)size); |
| 1361 | pp->mib_value.type = cpu_to_le16((uint16_t)type); |
| 1362 | memcpy(&pp->mib_value.body, vp, size); |
| 1363 | |
| 1364 | /* send to device request */ |
| 1365 | ps_confirm_wait_inc(priv); |
| 1366 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + size), NULL, NULL, NULL); |
| 1367 | } |
| 1368 | |
| 1369 | static |
| 1370 | void hostif_start_request( ks_wlan_private *priv, unsigned char mode ) |
| 1371 | { |
| 1372 | struct hostif_start_request_t *pp; |
| 1373 | |
| 1374 | DPRINTK(3,"\n"); |
| 1375 | |
| 1376 | /* make primitive */ |
| 1377 | pp = (struct hostif_start_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1378 | if (pp==NULL) { |
| 1379 | DPRINTK(3, "allocate memory failed..\n"); |
| 1380 | return; |
| 1381 | } |
| 1382 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1383 | pp->header.event = cpu_to_le16((uint16_t)HIF_START_REQ); |
| 1384 | pp->mode = cpu_to_le16((uint16_t)mode); |
| 1385 | |
| 1386 | /* send to device request */ |
| 1387 | ps_confirm_wait_inc(priv); |
| 1388 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1389 | |
| 1390 | priv->aplist.size = 0; |
| 1391 | priv->scan_ind_count=0; |
| 1392 | } |
| 1393 | |
| 1394 | static |
| 1395 | void hostif_ps_adhoc_set_request(ks_wlan_private *priv) |
| 1396 | { |
| 1397 | struct hostif_ps_adhoc_set_request_t *pp; |
| 1398 | uint16_t capability; |
| 1399 | |
| 1400 | DPRINTK(3,"\n"); |
| 1401 | |
| 1402 | /* make primitive */ |
| 1403 | pp = (struct hostif_ps_adhoc_set_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1404 | if (pp==NULL) { |
| 1405 | DPRINTK(3, "allocate memory failed..\n"); |
| 1406 | return; |
| 1407 | } |
| 1408 | memset(pp, 0, sizeof(*pp)); |
| 1409 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1410 | pp->header.event = cpu_to_le16((uint16_t)HIF_PS_ADH_SET_REQ); |
| 1411 | pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type)); |
| 1412 | pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode)); |
| 1413 | pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type)); |
| 1414 | pp->channel = cpu_to_le16((uint16_t)(priv->reg.channel)); |
| 1415 | pp->rate_set.size = priv->reg.rate_set.size; |
| 1416 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], priv->reg.rate_set.size); |
| 1417 | |
| 1418 | capability = 0x0000; |
| 1419 | if (priv->reg.preamble==SHORT_PREAMBLE) { |
| 1420 | /* short preamble */ |
| 1421 | capability |= BSS_CAP_SHORT_PREAMBLE; |
| 1422 | } |
| 1423 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
| 1424 | if(priv->reg.phy_type != D_11B_ONLY_MODE){ |
| 1425 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ |
| 1426 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM */ |
| 1427 | } |
| 1428 | pp->capability = cpu_to_le16((uint16_t)capability); |
| 1429 | |
| 1430 | /* send to device request */ |
| 1431 | ps_confirm_wait_inc(priv); |
| 1432 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1433 | } |
| 1434 | |
| 1435 | static |
| 1436 | void hostif_infrastructure_set_request(ks_wlan_private *priv) |
| 1437 | { |
| 1438 | struct hostif_infrastructure_set_request_t *pp; |
| 1439 | uint16_t capability; |
| 1440 | |
| 1441 | DPRINTK(3, "ssid.size=%d \n",priv->reg.ssid.size); |
| 1442 | |
| 1443 | /* make primitive */ |
| 1444 | pp = (struct hostif_infrastructure_set_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1445 | if (pp==NULL) { |
| 1446 | DPRINTK(3, "allocate memory failed..\n"); |
| 1447 | return; |
| 1448 | } |
| 1449 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1450 | pp->header.event = cpu_to_le16((uint16_t)HIF_INFRA_SET_REQ); |
| 1451 | pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type)); |
| 1452 | pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode)); |
| 1453 | pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type)); |
| 1454 | |
| 1455 | pp->rate_set.size = priv->reg.rate_set.size; |
| 1456 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], priv->reg.rate_set.size); |
| 1457 | pp->ssid.size = priv->reg.ssid.size; |
| 1458 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
| 1459 | |
| 1460 | capability = 0x0000; |
| 1461 | if (priv->reg.preamble==SHORT_PREAMBLE) { |
| 1462 | /* short preamble */ |
| 1463 | capability |= BSS_CAP_SHORT_PREAMBLE; |
| 1464 | } |
| 1465 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
| 1466 | if(priv->reg.phy_type != D_11B_ONLY_MODE){ |
| 1467 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ |
| 1468 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ |
| 1469 | } |
| 1470 | pp->capability = cpu_to_le16((uint16_t)capability); |
| 1471 | pp->beacon_lost_count = cpu_to_le16((uint16_t)(priv->reg.beacon_lost_count)); |
| 1472 | pp->auth_type = cpu_to_le16((uint16_t)(priv->reg.authenticate_type)); |
| 1473 | |
| 1474 | pp->channel_list.body[0] = 1; |
| 1475 | pp->channel_list.body[1] = 8; |
| 1476 | pp->channel_list.body[2] = 2; |
| 1477 | pp->channel_list.body[3] = 9; |
| 1478 | pp->channel_list.body[4] = 3; |
| 1479 | pp->channel_list.body[5] = 10; |
| 1480 | pp->channel_list.body[6] = 4; |
| 1481 | pp->channel_list.body[7] = 11; |
| 1482 | pp->channel_list.body[8] = 5; |
| 1483 | pp->channel_list.body[9] = 12; |
| 1484 | pp->channel_list.body[10] = 6; |
| 1485 | pp->channel_list.body[11] = 13; |
| 1486 | pp->channel_list.body[12] = 7; |
| 1487 | if(priv->reg.phy_type == D_11G_ONLY_MODE){ |
| 1488 | pp->channel_list.size = 13; |
| 1489 | }else{ |
| 1490 | pp->channel_list.body[13] = 14; |
| 1491 | pp->channel_list.size = 14; |
| 1492 | } |
| 1493 | |
| 1494 | /* send to device request */ |
| 1495 | ps_confirm_wait_inc(priv); |
| 1496 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)),NULL, NULL, NULL); |
| 1497 | } |
| 1498 | |
| 1499 | void hostif_infrastructure_set2_request(ks_wlan_private *priv) |
| 1500 | { |
| 1501 | struct hostif_infrastructure_set2_request_t *pp; |
| 1502 | uint16_t capability; |
| 1503 | |
| 1504 | DPRINTK(2, "ssid.size=%d \n",priv->reg.ssid.size); |
| 1505 | |
| 1506 | /* make primitive */ |
| 1507 | pp = (struct hostif_infrastructure_set2_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1508 | if (pp==NULL) { |
| 1509 | DPRINTK(3, "allocate memory failed..\n"); |
| 1510 | return; |
| 1511 | } |
| 1512 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1513 | pp->header.event = cpu_to_le16((uint16_t)HIF_INFRA_SET2_REQ); |
| 1514 | pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type)); |
| 1515 | pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode)); |
| 1516 | pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type)); |
| 1517 | |
| 1518 | pp->rate_set.size = priv->reg.rate_set.size; |
| 1519 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], priv->reg.rate_set.size); |
| 1520 | pp->ssid.size = priv->reg.ssid.size; |
| 1521 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
| 1522 | |
| 1523 | capability = 0x0000; |
| 1524 | if (priv->reg.preamble==SHORT_PREAMBLE) { |
| 1525 | /* short preamble */ |
| 1526 | capability |= BSS_CAP_SHORT_PREAMBLE; |
| 1527 | } |
| 1528 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
| 1529 | if(priv->reg.phy_type != D_11B_ONLY_MODE){ |
| 1530 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ |
| 1531 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ |
| 1532 | } |
| 1533 | pp->capability = cpu_to_le16((uint16_t)capability); |
| 1534 | pp->beacon_lost_count = cpu_to_le16((uint16_t)(priv->reg.beacon_lost_count)); |
| 1535 | pp->auth_type = cpu_to_le16((uint16_t)(priv->reg.authenticate_type)); |
| 1536 | |
| 1537 | pp->channel_list.body[0] = 1; |
| 1538 | pp->channel_list.body[1] = 8; |
| 1539 | pp->channel_list.body[2] = 2; |
| 1540 | pp->channel_list.body[3] = 9; |
| 1541 | pp->channel_list.body[4] = 3; |
| 1542 | pp->channel_list.body[5] = 10; |
| 1543 | pp->channel_list.body[6] = 4; |
| 1544 | pp->channel_list.body[7] = 11; |
| 1545 | pp->channel_list.body[8] = 5; |
| 1546 | pp->channel_list.body[9] = 12; |
| 1547 | pp->channel_list.body[10] = 6; |
| 1548 | pp->channel_list.body[11] = 13; |
| 1549 | pp->channel_list.body[12] = 7; |
| 1550 | if(priv->reg.phy_type == D_11G_ONLY_MODE){ |
| 1551 | pp->channel_list.size = 13; |
| 1552 | }else{ |
| 1553 | pp->channel_list.body[13] = 14; |
| 1554 | pp->channel_list.size = 14; |
| 1555 | } |
| 1556 | |
| 1557 | memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN); |
| 1558 | |
| 1559 | /* send to device request */ |
| 1560 | ps_confirm_wait_inc(priv); |
| 1561 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)),NULL, NULL, NULL); |
| 1562 | } |
| 1563 | |
| 1564 | static |
| 1565 | void hostif_adhoc_set_request(ks_wlan_private *priv) |
| 1566 | { |
| 1567 | struct hostif_adhoc_set_request_t *pp; |
| 1568 | uint16_t capability; |
| 1569 | |
| 1570 | DPRINTK(3, "\n"); |
| 1571 | |
| 1572 | /* make primitive */ |
| 1573 | pp = (struct hostif_adhoc_set_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1574 | if (pp==NULL) { |
| 1575 | DPRINTK(3, "allocate memory failed..\n"); |
| 1576 | return; |
| 1577 | } |
| 1578 | memset(pp, 0, sizeof(*pp)); |
| 1579 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1580 | pp->header.event = cpu_to_le16((uint16_t)HIF_ADH_SET_REQ); |
| 1581 | pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type)); |
| 1582 | pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode)); |
| 1583 | pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type)); |
| 1584 | pp->channel = cpu_to_le16((uint16_t)(priv->reg.channel)); |
| 1585 | pp->rate_set.size = priv->reg.rate_set.size; |
| 1586 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], priv->reg.rate_set.size); |
| 1587 | pp->ssid.size = priv->reg.ssid.size; |
| 1588 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
| 1589 | |
| 1590 | capability = 0x0000; |
| 1591 | if (priv->reg.preamble==SHORT_PREAMBLE) { |
| 1592 | /* short preamble */ |
| 1593 | capability |= BSS_CAP_SHORT_PREAMBLE; |
| 1594 | } |
| 1595 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
| 1596 | if(priv->reg.phy_type != D_11B_ONLY_MODE){ |
| 1597 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ |
| 1598 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ |
| 1599 | } |
| 1600 | pp->capability = cpu_to_le16((uint16_t)capability); |
| 1601 | |
| 1602 | /* send to device request */ |
| 1603 | ps_confirm_wait_inc(priv); |
| 1604 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1605 | } |
| 1606 | |
| 1607 | static |
| 1608 | void hostif_adhoc_set2_request(ks_wlan_private *priv) |
| 1609 | { |
| 1610 | struct hostif_adhoc_set2_request_t *pp; |
| 1611 | uint16_t capability; |
| 1612 | |
| 1613 | DPRINTK(3, "\n"); |
| 1614 | |
| 1615 | /* make primitive */ |
| 1616 | pp = (struct hostif_adhoc_set2_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1617 | if (pp==NULL) { |
| 1618 | DPRINTK(3, "allocate memory failed..\n"); |
| 1619 | return; |
| 1620 | } |
| 1621 | memset(pp, 0, sizeof(*pp)); |
| 1622 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1623 | pp->header.event = cpu_to_le16((uint16_t)HIF_ADH_SET_REQ); |
| 1624 | pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type)); |
| 1625 | pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode)); |
| 1626 | pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type)); |
| 1627 | pp->rate_set.size = priv->reg.rate_set.size; |
| 1628 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], priv->reg.rate_set.size); |
| 1629 | pp->ssid.size = priv->reg.ssid.size; |
| 1630 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); |
| 1631 | |
| 1632 | capability = 0x0000; |
| 1633 | if (priv->reg.preamble==SHORT_PREAMBLE) { |
| 1634 | /* short preamble */ |
| 1635 | capability |= BSS_CAP_SHORT_PREAMBLE; |
| 1636 | } |
| 1637 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
| 1638 | if(priv->reg.phy_type != D_11B_ONLY_MODE){ |
| 1639 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ |
| 1640 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ |
| 1641 | } |
| 1642 | pp->capability = cpu_to_le16((uint16_t)capability); |
| 1643 | |
| 1644 | pp->channel_list.body[0] = priv->reg.channel; |
| 1645 | pp->channel_list.size = 1; |
| 1646 | memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN); |
| 1647 | |
| 1648 | /* send to device request */ |
| 1649 | ps_confirm_wait_inc(priv); |
| 1650 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1651 | } |
| 1652 | |
| 1653 | static |
| 1654 | void hostif_stop_request( ks_wlan_private *priv ) |
| 1655 | { |
| 1656 | struct hostif_stop_request_t *pp; |
| 1657 | |
| 1658 | DPRINTK(3,"\n"); |
| 1659 | |
| 1660 | /* make primitive */ |
| 1661 | pp = (struct hostif_stop_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1662 | if (pp==NULL) { |
| 1663 | DPRINTK(3,"allocate memory failed..\n"); |
| 1664 | return; |
| 1665 | } |
| 1666 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1667 | pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ); |
| 1668 | |
| 1669 | /* send to device request */ |
| 1670 | ps_confirm_wait_inc(priv); |
| 1671 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1672 | } |
| 1673 | |
| 1674 | static |
| 1675 | void hostif_phy_information_request( ks_wlan_private *priv ) |
| 1676 | { |
| 1677 | struct hostif_phy_information_request_t *pp; |
| 1678 | |
| 1679 | DPRINTK(3,"\n"); |
| 1680 | |
| 1681 | /* make primitive */ |
| 1682 | pp = (struct hostif_phy_information_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1683 | if (pp==NULL) { |
| 1684 | DPRINTK(3, "allocate memory failed..\n"); |
| 1685 | return; |
| 1686 | } |
| 1687 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1688 | pp->header.event = cpu_to_le16((uint16_t)HIF_PHY_INFO_REQ); |
| 1689 | if(priv->reg.phy_info_timer){ |
| 1690 | pp->type = cpu_to_le16((uint16_t)TIME_TYPE); |
| 1691 | pp->time = cpu_to_le16((uint16_t)(priv->reg.phy_info_timer)); |
| 1692 | }else{ |
| 1693 | pp->type = cpu_to_le16((uint16_t)NORMAL_TYPE); |
| 1694 | pp->time = cpu_to_le16((uint16_t)0); |
| 1695 | } |
| 1696 | |
| 1697 | /* send to device request */ |
| 1698 | ps_confirm_wait_inc(priv); |
| 1699 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1700 | } |
| 1701 | |
| 1702 | static |
| 1703 | void hostif_power_mngmt_request( ks_wlan_private *priv, unsigned long mode, |
| 1704 | unsigned long wake_up, unsigned long receiveDTIMs ) |
| 1705 | { |
| 1706 | struct hostif_power_mngmt_request_t *pp; |
| 1707 | |
| 1708 | DPRINTK(3,"mode=%lu wake_up=%lu receiveDTIMs=%lu\n",mode,wake_up,receiveDTIMs); |
| 1709 | /* make primitive */ |
| 1710 | pp = (struct hostif_power_mngmt_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1711 | if (pp==NULL) { |
| 1712 | DPRINTK(3,"allocate memory failed..\n"); |
| 1713 | return; |
| 1714 | } |
| 1715 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1716 | pp->header.event = cpu_to_le16((uint16_t)HIF_POWERMGT_REQ); |
| 1717 | pp->mode = cpu_to_le32((uint32_t)mode); |
| 1718 | pp->wake_up = cpu_to_le32((uint32_t)wake_up); |
| 1719 | pp->receiveDTIMs = cpu_to_le32((uint32_t)receiveDTIMs); |
| 1720 | |
| 1721 | /* send to device request */ |
| 1722 | ps_confirm_wait_inc(priv); |
| 1723 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1724 | } |
| 1725 | |
| 1726 | static |
| 1727 | void hostif_sleep_request( ks_wlan_private *priv, unsigned long mode) |
| 1728 | { |
| 1729 | struct hostif_sleep_request_t *pp; |
| 1730 | |
| 1731 | DPRINTK(3,"mode=%lu \n",mode); |
| 1732 | |
| 1733 | if(mode == SLP_SLEEP){ |
| 1734 | /* make primitive */ |
| 1735 | pp = (struct hostif_sleep_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1736 | if (pp==NULL) { |
| 1737 | DPRINTK(3,"allocate memory failed..\n"); |
| 1738 | return; |
| 1739 | } |
| 1740 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1741 | pp->header.event = cpu_to_le16((uint16_t)HIF_SLEEP_REQ); |
| 1742 | |
| 1743 | /* send to device request */ |
| 1744 | ps_confirm_wait_inc(priv); |
| 1745 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1746 | }else if(mode == SLP_ACTIVE){ |
| 1747 | atomic_set(&priv->sleepstatus.wakeup_request,1); |
| 1748 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, 1); |
| 1749 | }else{ |
| 1750 | DPRINTK(3,"invalid mode %ld \n", mode); |
| 1751 | return; |
| 1752 | } |
| 1753 | } |
| 1754 | |
| 1755 | |
| 1756 | static |
| 1757 | void hostif_bss_scan_request( ks_wlan_private *priv, unsigned long scan_type , uint8_t *scan_ssid, uint8_t scan_ssid_len) |
| 1758 | { |
| 1759 | struct hostif_bss_scan_request_t *pp; |
| 1760 | |
| 1761 | DPRINTK(2,"\n"); |
| 1762 | /* make primitive */ |
| 1763 | pp = (struct hostif_bss_scan_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1764 | if (pp==NULL) { |
| 1765 | DPRINTK(3,"allocate memory failed..\n"); |
| 1766 | return; |
| 1767 | } |
| 1768 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1769 | pp->header.event = cpu_to_le16((uint16_t)HIF_SCAN_REQ); |
| 1770 | pp->scan_type = scan_type; |
| 1771 | |
| 1772 | pp->ch_time_min = cpu_to_le32((uint32_t)110); /* default value */ |
| 1773 | pp->ch_time_max = cpu_to_le32((uint32_t)130); /* default value */ |
| 1774 | pp->channel_list.body[0] = 1; |
| 1775 | pp->channel_list.body[1] = 8; |
| 1776 | pp->channel_list.body[2] = 2; |
| 1777 | pp->channel_list.body[3] = 9; |
| 1778 | pp->channel_list.body[4] = 3; |
| 1779 | pp->channel_list.body[5] = 10; |
| 1780 | pp->channel_list.body[6] = 4; |
| 1781 | pp->channel_list.body[7] = 11; |
| 1782 | pp->channel_list.body[8] = 5; |
| 1783 | pp->channel_list.body[9] = 12; |
| 1784 | pp->channel_list.body[10] = 6; |
| 1785 | pp->channel_list.body[11] = 13; |
| 1786 | pp->channel_list.body[12] = 7; |
| 1787 | if(priv->reg.phy_type == D_11G_ONLY_MODE){ |
| 1788 | pp->channel_list.size = 13; |
| 1789 | }else{ |
| 1790 | pp->channel_list.body[13] = 14; |
| 1791 | pp->channel_list.size = 14; |
| 1792 | } |
| 1793 | pp->ssid.size = 0; |
| 1794 | |
| 1795 | /* specified SSID SCAN */ |
| 1796 | if(scan_ssid_len > 0 && scan_ssid_len <= 32){ |
| 1797 | pp->ssid.size = scan_ssid_len; |
| 1798 | memcpy(&pp->ssid.body[0], scan_ssid, scan_ssid_len); |
| 1799 | } |
| 1800 | |
| 1801 | |
| 1802 | /* send to device request */ |
| 1803 | ps_confirm_wait_inc(priv); |
| 1804 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1805 | |
| 1806 | priv->aplist.size = 0; |
| 1807 | priv->scan_ind_count=0; |
| 1808 | } |
| 1809 | |
| 1810 | static |
| 1811 | void hostif_mic_failure_request( ks_wlan_private *priv, unsigned short failure_count, |
| 1812 | unsigned short timer ) |
| 1813 | { |
| 1814 | struct hostif_mic_failure_request_t *pp; |
| 1815 | |
| 1816 | DPRINTK(3,"count=%d :: timer=%d\n",failure_count,timer); |
| 1817 | /* make primitive */ |
| 1818 | pp = (struct hostif_mic_failure_request_t *)kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG ); |
| 1819 | if (pp==NULL) { |
| 1820 | DPRINTK(3,"allocate memory failed..\n"); |
| 1821 | return; |
| 1822 | } |
| 1823 | pp->header.size = cpu_to_le16((uint16_t)(sizeof(*pp)-sizeof(pp->header.size))); |
| 1824 | pp->header.event = cpu_to_le16((uint16_t)HIF_MIC_FAILURE_REQ); |
| 1825 | pp->failure_count = cpu_to_le16((uint16_t)failure_count); |
| 1826 | pp->timer = cpu_to_le16((uint16_t)timer); |
| 1827 | |
| 1828 | /* send to device request */ |
| 1829 | ps_confirm_wait_inc(priv); |
| 1830 | ks_wlan_hw_tx( priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
| 1831 | } |
| 1832 | |
| 1833 | /* Device I/O Recieve indicate */ |
| 1834 | static void devio_rec_ind(ks_wlan_private *priv, unsigned char *p, unsigned int size) |
| 1835 | { |
| 1836 | if (priv->device_open_status) { |
| 1837 | spin_lock(&priv->dev_read_lock); /* request spin lock */ |
| 1838 | priv->dev_data[atomic_read(&priv->rec_count)] = p; |
| 1839 | priv->dev_size[atomic_read(&priv->rec_count)] = size; |
| 1840 | |
| 1841 | if (atomic_read(&priv->event_count) != DEVICE_STOCK_COUNT) { |
| 1842 | /* rx event count inc */ |
| 1843 | atomic_inc(&priv->event_count); |
| 1844 | } |
| 1845 | atomic_inc(&priv->rec_count); |
| 1846 | if (atomic_read(&priv->rec_count)==DEVICE_STOCK_COUNT) |
| 1847 | atomic_set(&priv->rec_count, 0); |
| 1848 | |
| 1849 | wake_up_interruptible_all(&priv->devread_wait); |
| 1850 | |
| 1851 | /* release spin lock */ |
| 1852 | spin_unlock(&priv->dev_read_lock); |
| 1853 | } |
| 1854 | } |
| 1855 | |
| 1856 | void hostif_receive( ks_wlan_private *priv, unsigned char *p, unsigned int size ) |
| 1857 | { |
| 1858 | DPRINTK(4,"\n"); |
| 1859 | |
| 1860 | devio_rec_ind(priv, p, size); |
| 1861 | |
| 1862 | priv->rxp = p; |
| 1863 | priv->rx_size = size; |
| 1864 | |
| 1865 | if (get_WORD(priv) == priv->rx_size) { /* length check !! */ |
| 1866 | hostif_event_check(priv); /* event check */ |
| 1867 | } |
| 1868 | } |
| 1869 | |
| 1870 | |
| 1871 | static |
| 1872 | void hostif_sme_set_wep(ks_wlan_private *priv, int type) |
| 1873 | { |
| 1874 | uint32_t val; |
| 1875 | switch(type){ |
| 1876 | case SME_WEP_INDEX_REQUEST: |
| 1877 | val = cpu_to_le32((uint32_t)(priv->reg.wep_index)); |
| 1878 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID, |
| 1879 | sizeof(val), MIB_VALUE_TYPE_INT, |
| 1880 | &val ); |
| 1881 | break; |
| 1882 | case SME_WEP_KEY1_REQUEST: |
| 1883 | if(!priv->wpa.wpa_enabled) |
| 1884 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE1, |
| 1885 | priv->reg.wep_key[0].size, MIB_VALUE_TYPE_OSTRING, |
| 1886 | &priv->reg.wep_key[0].val[0] ); |
| 1887 | break; |
| 1888 | case SME_WEP_KEY2_REQUEST: |
| 1889 | if(!priv->wpa.wpa_enabled) |
| 1890 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE2, |
| 1891 | priv->reg.wep_key[1].size, MIB_VALUE_TYPE_OSTRING, |
| 1892 | &priv->reg.wep_key[1].val[0]); |
| 1893 | break; |
| 1894 | case SME_WEP_KEY3_REQUEST: |
| 1895 | if(!priv->wpa.wpa_enabled) |
| 1896 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE3, |
| 1897 | priv->reg.wep_key[2].size, MIB_VALUE_TYPE_OSTRING, |
| 1898 | &priv->reg.wep_key[2].val[0] ); |
| 1899 | break; |
| 1900 | case SME_WEP_KEY4_REQUEST: |
| 1901 | if(!priv->wpa.wpa_enabled) |
| 1902 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE4, |
| 1903 | priv->reg.wep_key[3].size, MIB_VALUE_TYPE_OSTRING, |
| 1904 | &priv->reg.wep_key[3].val[0]); |
| 1905 | break; |
| 1906 | case SME_WEP_FLAG_REQUEST: |
| 1907 | val = cpu_to_le32((uint32_t)(priv->reg.privacy_invoked)); |
| 1908 | hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED, |
| 1909 | sizeof(val), MIB_VALUE_TYPE_BOOL, |
| 1910 | &val ); |
| 1911 | break; |
| 1912 | } |
| 1913 | |
| 1914 | return ; |
| 1915 | } |
| 1916 | |
| 1917 | struct wpa_suite_t { |
| 1918 | unsigned short size; |
| 1919 | unsigned char suite[4][CIPHER_ID_LEN]; |
| 1920 | } __attribute__((packed)); |
| 1921 | |
| 1922 | struct rsn_mode_t { |
| 1923 | uint32_t rsn_mode; |
| 1924 | uint16_t rsn_capability; |
| 1925 | } __attribute__((packed)); |
| 1926 | |
| 1927 | static |
| 1928 | void hostif_sme_set_rsn(ks_wlan_private *priv, int type) |
| 1929 | { |
| 1930 | struct wpa_suite_t wpa_suite; |
| 1931 | struct rsn_mode_t rsn_mode; |
| 1932 | uint32_t val; |
| 1933 | |
| 1934 | memset(&wpa_suite,0,sizeof(wpa_suite)); |
| 1935 | |
| 1936 | switch(type){ |
| 1937 | case SME_RSN_UCAST_REQUEST: |
| 1938 | wpa_suite.size=cpu_to_le16((uint16_t)1); |
| 1939 | switch(priv->wpa.pairwise_suite){ |
| 1940 | case IW_AUTH_CIPHER_NONE: |
| 1941 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1942 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_NONE,CIPHER_ID_LEN); |
| 1943 | else |
| 1944 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_NONE,CIPHER_ID_LEN); |
| 1945 | break; |
| 1946 | case IW_AUTH_CIPHER_WEP40: |
| 1947 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1948 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_WEP40,CIPHER_ID_LEN); |
| 1949 | else |
| 1950 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_WEP40,CIPHER_ID_LEN); |
| 1951 | break; |
| 1952 | case IW_AUTH_CIPHER_TKIP: |
| 1953 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1954 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_TKIP,CIPHER_ID_LEN); |
| 1955 | else |
| 1956 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_TKIP,CIPHER_ID_LEN); |
| 1957 | break; |
| 1958 | case IW_AUTH_CIPHER_CCMP: |
| 1959 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1960 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_CCMP,CIPHER_ID_LEN); |
| 1961 | else |
| 1962 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_CCMP,CIPHER_ID_LEN); |
| 1963 | break; |
| 1964 | case IW_AUTH_CIPHER_WEP104: |
| 1965 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1966 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_WEP104,CIPHER_ID_LEN); |
| 1967 | else |
| 1968 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_WEP104,CIPHER_ID_LEN); |
| 1969 | break; |
| 1970 | } |
| 1971 | |
| 1972 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_UNICAST_CIPHER, |
| 1973 | sizeof(wpa_suite.size)+CIPHER_ID_LEN*wpa_suite.size, |
| 1974 | MIB_VALUE_TYPE_OSTRING, &wpa_suite); |
| 1975 | break; |
| 1976 | case SME_RSN_MCAST_REQUEST: |
| 1977 | switch(priv->wpa.group_suite){ |
| 1978 | case IW_AUTH_CIPHER_NONE: |
| 1979 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1980 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_NONE,CIPHER_ID_LEN); |
| 1981 | else |
| 1982 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_NONE,CIPHER_ID_LEN); |
| 1983 | break; |
| 1984 | case IW_AUTH_CIPHER_WEP40: |
| 1985 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1986 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_WEP40,CIPHER_ID_LEN); |
| 1987 | else |
| 1988 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_WEP40,CIPHER_ID_LEN); |
| 1989 | break; |
| 1990 | case IW_AUTH_CIPHER_TKIP: |
| 1991 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1992 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_TKIP,CIPHER_ID_LEN); |
| 1993 | else |
| 1994 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_TKIP,CIPHER_ID_LEN); |
| 1995 | break; |
| 1996 | case IW_AUTH_CIPHER_CCMP: |
| 1997 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 1998 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_CCMP,CIPHER_ID_LEN); |
| 1999 | else |
| 2000 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_CCMP,CIPHER_ID_LEN); |
| 2001 | break; |
| 2002 | case IW_AUTH_CIPHER_WEP104: |
| 2003 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 2004 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA2_WEP104,CIPHER_ID_LEN); |
| 2005 | else |
| 2006 | memcpy(&wpa_suite.suite[0][0],CIPHER_ID_WPA_WEP104,CIPHER_ID_LEN); |
| 2007 | break; |
| 2008 | } |
| 2009 | |
| 2010 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_MULTICAST_CIPHER, |
| 2011 | CIPHER_ID_LEN, MIB_VALUE_TYPE_OSTRING, |
| 2012 | &wpa_suite.suite[0][0] ); |
| 2013 | break; |
| 2014 | case SME_RSN_AUTH_REQUEST: |
| 2015 | wpa_suite.size=cpu_to_le16((uint16_t)1); |
| 2016 | switch(priv->wpa.key_mgmt_suite){ |
| 2017 | case IW_AUTH_KEY_MGMT_802_1X: |
| 2018 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 2019 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA2_1X,KEY_MGMT_ID_LEN); |
| 2020 | else |
| 2021 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA_1X,KEY_MGMT_ID_LEN); |
| 2022 | break; |
| 2023 | case IW_AUTH_KEY_MGMT_PSK: |
| 2024 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 2025 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA2_PSK,KEY_MGMT_ID_LEN); |
| 2026 | else |
| 2027 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA_PSK,KEY_MGMT_ID_LEN); |
| 2028 | break; |
| 2029 | case 0: |
| 2030 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 2031 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA2_NONE,KEY_MGMT_ID_LEN); |
| 2032 | else |
| 2033 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA_NONE,KEY_MGMT_ID_LEN); |
| 2034 | break; |
| 2035 | case 4: |
| 2036 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
| 2037 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA2_WPANONE,KEY_MGMT_ID_LEN); |
| 2038 | else |
| 2039 | memcpy(&wpa_suite.suite[0][0],KEY_MGMT_ID_WPA_WPANONE,KEY_MGMT_ID_LEN); |
| 2040 | break; |
| 2041 | } |
| 2042 | |
| 2043 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_AUTH_SUITE, |
| 2044 | sizeof(wpa_suite.size)+KEY_MGMT_ID_LEN*wpa_suite.size, |
| 2045 | MIB_VALUE_TYPE_OSTRING, &wpa_suite); |
| 2046 | break; |
| 2047 | case SME_RSN_ENABLED_REQUEST: |
| 2048 | val = cpu_to_le32((uint32_t)(priv->wpa.rsn_enabled)); |
| 2049 | hostif_mib_set_request(priv, DOT11_RSN_ENABLED, |
| 2050 | sizeof(val), MIB_VALUE_TYPE_BOOL, |
| 2051 | &val ); |
| 2052 | break; |
| 2053 | case SME_RSN_MODE_REQUEST: |
| 2054 | if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2){ |
| 2055 | rsn_mode.rsn_mode = cpu_to_le32((uint32_t)RSN_MODE_WPA2); |
| 2056 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0); |
| 2057 | } |
| 2058 | else if(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA){ |
| 2059 | rsn_mode.rsn_mode = cpu_to_le32((uint32_t)RSN_MODE_WPA); |
| 2060 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0); |
| 2061 | } |
| 2062 | else{ |
| 2063 | rsn_mode.rsn_mode = cpu_to_le32((uint32_t)RSN_MODE_NONE); |
| 2064 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0); |
| 2065 | } |
| 2066 | hostif_mib_set_request(priv, LOCAL_RSN_MODE,sizeof(rsn_mode), |
| 2067 | MIB_VALUE_TYPE_OSTRING,&rsn_mode ); |
| 2068 | break; |
| 2069 | |
| 2070 | } |
| 2071 | return; |
| 2072 | } |
| 2073 | |
| 2074 | static |
| 2075 | void hostif_sme_mode_setup(ks_wlan_private *priv) |
| 2076 | { |
| 2077 | unsigned char rate_size; |
| 2078 | unsigned char rate_octet[RATE_SET_MAX_SIZE]; |
| 2079 | int i=0; |
| 2080 | |
| 2081 | /* rate setting if rate segging is auto for changing phy_type (#94)*/ |
| 2082 | if(priv->reg.tx_rate == TX_RATE_FULL_AUTO){ |
| 2083 | if(priv->reg.phy_type == D_11B_ONLY_MODE){ |
| 2084 | priv->reg.rate_set.body[3] = TX_RATE_11M; |
| 2085 | priv->reg.rate_set.body[2] = TX_RATE_5M; |
| 2086 | priv->reg.rate_set.body[1] = TX_RATE_2M|BASIC_RATE; |
| 2087 | priv->reg.rate_set.body[0] = TX_RATE_1M|BASIC_RATE; |
| 2088 | priv->reg.rate_set.size = 4; |
| 2089 | }else{ /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
| 2090 | priv->reg.rate_set.body[11] = TX_RATE_54M; |
| 2091 | priv->reg.rate_set.body[10] = TX_RATE_48M; |
| 2092 | priv->reg.rate_set.body[9] = TX_RATE_36M; |
| 2093 | priv->reg.rate_set.body[8] = TX_RATE_18M; |
| 2094 | priv->reg.rate_set.body[7] = TX_RATE_9M; |
| 2095 | priv->reg.rate_set.body[6] = TX_RATE_24M|BASIC_RATE; |
| 2096 | priv->reg.rate_set.body[5] = TX_RATE_12M|BASIC_RATE; |
| 2097 | priv->reg.rate_set.body[4] = TX_RATE_6M|BASIC_RATE; |
| 2098 | priv->reg.rate_set.body[3] = TX_RATE_11M|BASIC_RATE; |
| 2099 | priv->reg.rate_set.body[2] = TX_RATE_5M|BASIC_RATE; |
| 2100 | priv->reg.rate_set.body[1] = TX_RATE_2M|BASIC_RATE; |
| 2101 | priv->reg.rate_set.body[0] = TX_RATE_1M|BASIC_RATE; |
| 2102 | priv->reg.rate_set.size = 12; |
| 2103 | } |
| 2104 | } |
| 2105 | |
| 2106 | /* rate mask by phy setting */ |
| 2107 | if(priv->reg.phy_type == D_11B_ONLY_MODE){ |
| 2108 | for(i=0;i<priv->reg.rate_set.size;i++){ |
| 2109 | if(IS_11B_RATE(priv->reg.rate_set.body[i])){ |
| 2110 | if((priv->reg.rate_set.body[i] & RATE_MASK) >= TX_RATE_5M) |
| 2111 | rate_octet[i] = priv->reg.rate_set.body[i] & RATE_MASK ; |
| 2112 | else |
| 2113 | rate_octet[i] = priv->reg.rate_set.body[i]; |
| 2114 | } |
| 2115 | else |
| 2116 | break; |
| 2117 | } |
| 2118 | |
| 2119 | }else{ /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
| 2120 | for(i=0;i<priv->reg.rate_set.size;i++){ |
| 2121 | if(IS_11BG_RATE(priv->reg.rate_set.body[i])){ |
| 2122 | if(IS_OFDM_EXT_RATE(priv->reg.rate_set.body[i])) |
| 2123 | rate_octet[i] = priv->reg.rate_set.body[i] & RATE_MASK ; |
| 2124 | else |
| 2125 | rate_octet[i] = priv->reg.rate_set.body[i]; |
| 2126 | } |
| 2127 | else |
| 2128 | break; |
| 2129 | } |
| 2130 | } |
| 2131 | rate_size = i; |
| 2132 | if(rate_size==0){ |
| 2133 | if(priv->reg.phy_type == D_11G_ONLY_MODE) |
| 2134 | rate_octet[0]=TX_RATE_6M | BASIC_RATE; |
| 2135 | else |
| 2136 | rate_octet[0]=TX_RATE_2M | BASIC_RATE; |
| 2137 | rate_size = 1; |
| 2138 | } |
| 2139 | |
| 2140 | /* rate set update */ |
| 2141 | priv->reg.rate_set.size = rate_size; |
| 2142 | memcpy(&priv->reg.rate_set.body[0], &rate_octet[0], rate_size); |
| 2143 | |
| 2144 | switch ( priv->reg.operation_mode ) { |
| 2145 | case MODE_PSEUDO_ADHOC: |
| 2146 | /* Pseudo Ad-Hoc mode */ |
| 2147 | hostif_ps_adhoc_set_request(priv); |
| 2148 | break; |
| 2149 | case MODE_INFRASTRUCTURE: |
| 2150 | /* Infrastructure mode */ |
| 2151 | if (!is_valid_ether_addr((u8 *)priv->reg.bssid)) { |
| 2152 | hostif_infrastructure_set_request(priv); |
| 2153 | } |
| 2154 | else { |
| 2155 | hostif_infrastructure_set2_request(priv); |
| 2156 | DPRINTK(2, "Infra bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 2157 | priv->reg.bssid[0],priv->reg.bssid[1],priv->reg.bssid[2], |
| 2158 | priv->reg.bssid[3],priv->reg.bssid[4],priv->reg.bssid[5]); |
| 2159 | } |
| 2160 | break; |
| 2161 | case MODE_ADHOC: |
| 2162 | /* IEEE802.11 Ad-Hoc mode */ |
| 2163 | if (!is_valid_ether_addr((u8 *)priv->reg.bssid)) { |
| 2164 | hostif_adhoc_set_request(priv); |
| 2165 | } |
| 2166 | else { |
| 2167 | hostif_adhoc_set2_request(priv); |
| 2168 | DPRINTK(2, "Adhoc bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", |
| 2169 | priv->reg.bssid[0],priv->reg.bssid[1],priv->reg.bssid[2], |
| 2170 | priv->reg.bssid[3],priv->reg.bssid[4],priv->reg.bssid[5]); |
| 2171 | } |
| 2172 | break; |
| 2173 | default: |
| 2174 | break; |
| 2175 | } |
| 2176 | |
| 2177 | return ; |
| 2178 | } |
| 2179 | |
| 2180 | static |
| 2181 | void hostif_sme_multicast_set(ks_wlan_private *priv) |
| 2182 | { |
| 2183 | |
| 2184 | struct net_device *dev = priv->net_dev; |
| 2185 | int mc_count; |
| 2186 | struct dev_mc_list *mclist; |
| 2187 | char set_address[NIC_MAX_MCAST_LIST*ETH_ALEN]; |
| 2188 | unsigned long filter_type; |
| 2189 | int i; |
| 2190 | |
| 2191 | DPRINTK(3,"\n"); |
| 2192 | |
| 2193 | spin_lock(&priv->multicast_spin); |
| 2194 | |
| 2195 | memset(set_address, 0, NIC_MAX_MCAST_LIST*ETH_ALEN); |
| 2196 | |
| 2197 | if (dev->flags & IFF_PROMISC ){ |
| 2198 | filter_type = cpu_to_le32((uint32_t)MCAST_FILTER_PROMISC); |
| 2199 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, sizeof(filter_type), |
| 2200 | MIB_VALUE_TYPE_BOOL, &filter_type); |
| 2201 | } |
| 2202 | else if ((dev->mc_count > NIC_MAX_MCAST_LIST) || (dev->flags & IFF_ALLMULTI)){ |
| 2203 | filter_type = cpu_to_le32((uint32_t)MCAST_FILTER_MCASTALL); |
| 2204 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, sizeof(filter_type), |
| 2205 | MIB_VALUE_TYPE_BOOL, &filter_type); |
| 2206 | } |
| 2207 | else { |
| 2208 | if (priv->sme_i.sme_flag & SME_MULTICAST){ |
| 2209 | mc_count = dev->mc_count; |
| 2210 | for (i = 0, mclist = dev->mc_list; mclist && i < mc_count; i++, mclist = mclist->next) |
| 2211 | memcpy(&set_address[i*ETH_ALEN], mclist->dmi_addr, ETH_ALEN); |
| 2212 | priv->sme_i.sme_flag &= ~SME_MULTICAST; |
| 2213 | hostif_mib_set_request(priv, LOCAL_MULTICAST_ADDRESS, |
| 2214 | (ETH_ALEN*mc_count), MIB_VALUE_TYPE_OSTRING, &set_address[0]); |
| 2215 | }else { |
| 2216 | filter_type = cpu_to_le32((uint32_t)MCAST_FILTER_MCAST); |
| 2217 | priv->sme_i.sme_flag |= SME_MULTICAST; |
| 2218 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, sizeof(filter_type), |
| 2219 | MIB_VALUE_TYPE_BOOL, &filter_type); |
| 2220 | } |
| 2221 | } |
| 2222 | |
| 2223 | spin_unlock(&priv->multicast_spin); |
| 2224 | |
| 2225 | } |
| 2226 | |
| 2227 | static |
| 2228 | void hostif_sme_powermgt_set(ks_wlan_private *priv) |
| 2229 | { |
| 2230 | unsigned long mode,wake_up,receiveDTIMs ; |
| 2231 | |
| 2232 | DPRINTK(3,"\n"); |
| 2233 | switch(priv->reg.powermgt){ |
| 2234 | case POWMGT_ACTIVE_MODE: |
| 2235 | mode = POWER_ACTIVE; |
| 2236 | wake_up = 0; |
| 2237 | receiveDTIMs = 0; |
| 2238 | break; |
| 2239 | case POWMGT_SAVE1_MODE: |
| 2240 | if(priv->reg.operation_mode == MODE_INFRASTRUCTURE){ |
| 2241 | mode = POWER_SAVE; |
| 2242 | wake_up = 0; |
| 2243 | receiveDTIMs = 0; |
| 2244 | } else { |
| 2245 | mode = POWER_ACTIVE; |
| 2246 | wake_up = 0; |
| 2247 | receiveDTIMs = 0; |
| 2248 | } |
| 2249 | break; |
| 2250 | case POWMGT_SAVE2_MODE: |
| 2251 | if(priv->reg.operation_mode == MODE_INFRASTRUCTURE){ |
| 2252 | mode = POWER_SAVE; |
| 2253 | wake_up = 0; |
| 2254 | receiveDTIMs = 1; |
| 2255 | } else { |
| 2256 | mode = POWER_ACTIVE; |
| 2257 | wake_up = 0; |
| 2258 | receiveDTIMs = 0; |
| 2259 | } |
| 2260 | break; |
| 2261 | default: |
| 2262 | mode = POWER_ACTIVE; |
| 2263 | wake_up = 0; |
| 2264 | receiveDTIMs = 0; |
| 2265 | break; |
| 2266 | } |
| 2267 | hostif_power_mngmt_request(priv, mode, wake_up, receiveDTIMs); |
| 2268 | |
| 2269 | return; |
| 2270 | } |
| 2271 | |
| 2272 | static |
| 2273 | void hostif_sme_sleep_set(ks_wlan_private *priv) |
| 2274 | { |
| 2275 | DPRINTK(3,"\n"); |
| 2276 | switch(priv->sleep_mode){ |
| 2277 | case SLP_SLEEP: |
| 2278 | hostif_sleep_request(priv, priv->sleep_mode); |
| 2279 | break; |
| 2280 | case SLP_ACTIVE: |
| 2281 | hostif_sleep_request(priv, priv->sleep_mode); |
| 2282 | break; |
| 2283 | default: |
| 2284 | break; |
| 2285 | } |
| 2286 | |
| 2287 | return; |
| 2288 | } |
| 2289 | |
| 2290 | static |
| 2291 | void hostif_sme_set_key(ks_wlan_private *priv, int type) |
| 2292 | { |
| 2293 | uint32_t val; |
| 2294 | switch(type){ |
| 2295 | case SME_SET_FLAG: |
| 2296 | val = cpu_to_le32((uint32_t)(priv->reg.privacy_invoked)); |
| 2297 | hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED, |
| 2298 | sizeof(val), MIB_VALUE_TYPE_BOOL, |
| 2299 | &val ); |
| 2300 | break; |
| 2301 | case SME_SET_TXKEY: |
| 2302 | val = cpu_to_le32((uint32_t)(priv->wpa.txkey)); |
| 2303 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID, |
| 2304 | sizeof(val), MIB_VALUE_TYPE_INT, |
| 2305 | &val ); |
| 2306 | break; |
| 2307 | case SME_SET_KEY1: |
| 2308 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE1, |
| 2309 | priv->wpa.key[0].key_len, MIB_VALUE_TYPE_OSTRING, |
| 2310 | &priv->wpa.key[0].key_val[0] ); |
| 2311 | break; |
| 2312 | case SME_SET_KEY2: |
| 2313 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE2, |
| 2314 | priv->wpa.key[1].key_len, MIB_VALUE_TYPE_OSTRING, |
| 2315 | &priv->wpa.key[1].key_val[0] ); |
| 2316 | break; |
| 2317 | case SME_SET_KEY3: |
| 2318 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE3, |
| 2319 | priv->wpa.key[2].key_len, MIB_VALUE_TYPE_OSTRING, |
| 2320 | &priv->wpa.key[2].key_val[0] ); |
| 2321 | break; |
| 2322 | case SME_SET_KEY4: |
| 2323 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE4, |
| 2324 | priv->wpa.key[3].key_len, MIB_VALUE_TYPE_OSTRING, |
| 2325 | &priv->wpa.key[3].key_val[0] ); |
| 2326 | break; |
| 2327 | case SME_SET_PMK_TSC: |
| 2328 | hostif_mib_set_request(priv, DOT11_PMK_TSC, |
| 2329 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, |
| 2330 | &priv->wpa.key[0].rx_seq[0] ); |
| 2331 | break; |
| 2332 | case SME_SET_GMK1_TSC: |
| 2333 | hostif_mib_set_request(priv, DOT11_GMK1_TSC, |
| 2334 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, |
| 2335 | &priv->wpa.key[1].rx_seq[0] ); |
| 2336 | break; |
| 2337 | case SME_SET_GMK2_TSC: |
| 2338 | hostif_mib_set_request(priv, DOT11_GMK2_TSC, |
| 2339 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, |
| 2340 | &priv->wpa.key[2].rx_seq[0] ); |
| 2341 | break; |
| 2342 | } |
| 2343 | return; |
| 2344 | } |
| 2345 | |
| 2346 | static |
| 2347 | void hostif_sme_set_pmksa(ks_wlan_private *priv) |
| 2348 | { |
| 2349 | struct pmk_cache_t { |
| 2350 | uint16_t size; |
| 2351 | struct { |
| 2352 | uint8_t bssid[ETH_ALEN]; |
| 2353 | uint8_t pmkid[IW_PMKID_LEN]; |
| 2354 | } __attribute__((packed)) list[PMK_LIST_MAX]; |
| 2355 | } __attribute__((packed)) pmkcache; |
| 2356 | struct pmk_t *pmk; |
| 2357 | struct list_head *ptr; |
| 2358 | int i; |
| 2359 | |
| 2360 | DPRINTK(4,"pmklist.size=%d\n",priv->pmklist.size); |
| 2361 | i=0; |
| 2362 | list_for_each(ptr, &priv->pmklist.head){ |
| 2363 | pmk = list_entry(ptr, struct pmk_t, list); |
| 2364 | if(i<PMK_LIST_MAX){ |
| 2365 | memcpy(pmkcache.list[i].bssid, pmk->bssid, ETH_ALEN); |
| 2366 | memcpy(pmkcache.list[i].pmkid, pmk->pmkid, IW_PMKID_LEN); |
| 2367 | i++; |
| 2368 | } |
| 2369 | } |
| 2370 | pmkcache.size = cpu_to_le16((uint16_t)(priv->pmklist.size)); |
| 2371 | hostif_mib_set_request(priv, LOCAL_PMK, |
| 2372 | sizeof(priv->pmklist.size)+(ETH_ALEN+IW_PMKID_LEN)*(priv->pmklist.size), |
| 2373 | MIB_VALUE_TYPE_OSTRING,&pmkcache ); |
| 2374 | } |
| 2375 | |
| 2376 | /* execute sme */ |
| 2377 | static |
| 2378 | void hostif_sme_execute(ks_wlan_private *priv, int event) |
| 2379 | { |
| 2380 | uint32_t val; |
| 2381 | |
| 2382 | DPRINTK(3,"event=%d\n",event); |
| 2383 | switch (event) { |
| 2384 | case SME_START: |
| 2385 | if ( priv->dev_state == DEVICE_STATE_BOOT ){ |
| 2386 | hostif_mib_get_request(priv, DOT11_MAC_ADDRESS); |
| 2387 | } |
| 2388 | break; |
| 2389 | case SME_MULTICAST_REQUEST: |
| 2390 | hostif_sme_multicast_set(priv); |
| 2391 | break; |
| 2392 | case SME_MACADDRESS_SET_REQUEST: |
| 2393 | hostif_mib_set_request(priv, LOCAL_CURRENTADDRESS, ETH_ALEN, |
| 2394 | MIB_VALUE_TYPE_OSTRING, &priv->eth_addr[0]); |
| 2395 | break; |
| 2396 | case SME_BSS_SCAN_REQUEST: |
| 2397 | hostif_bss_scan_request(priv, priv->reg.scan_type, priv->scan_ssid, priv->scan_ssid_len); |
| 2398 | break; |
| 2399 | case SME_POW_MNGMT_REQUEST: |
| 2400 | hostif_sme_powermgt_set(priv); |
| 2401 | break; |
| 2402 | case SME_PHY_INFO_REQUEST: |
| 2403 | hostif_phy_information_request(priv); |
| 2404 | break; |
| 2405 | case SME_MIC_FAILURE_REQUEST: |
| 2406 | if(priv->wpa.mic_failure.failure == 1){ |
| 2407 | hostif_mic_failure_request(priv, priv->wpa.mic_failure.failure-1, 0); |
| 2408 | }else if(priv->wpa.mic_failure.failure == 2){ |
| 2409 | hostif_mic_failure_request(priv, priv->wpa.mic_failure.failure-1, |
| 2410 | priv->wpa.mic_failure.counter); |
| 2411 | }else |
| 2412 | DPRINTK(4,"SME_MIC_FAILURE_REQUEST: failure count=%u error?\n", |
| 2413 | priv->wpa.mic_failure.failure); |
| 2414 | break; |
| 2415 | case SME_MIC_FAILURE_CONFIRM: |
| 2416 | if(priv->wpa.mic_failure.failure == 2){ |
| 2417 | if(priv->wpa.mic_failure.stop) |
| 2418 | priv->wpa.mic_failure.stop = 0; |
| 2419 | priv->wpa.mic_failure.failure = 0; |
| 2420 | hostif_start_request( priv, priv->reg.operation_mode ); |
| 2421 | } |
| 2422 | break; |
| 2423 | case SME_GET_MAC_ADDRESS: |
| 2424 | if ( priv->dev_state == DEVICE_STATE_BOOT ){ |
| 2425 | hostif_mib_get_request(priv, DOT11_PRODUCT_VERSION); |
| 2426 | } |
| 2427 | break; |
| 2428 | case SME_GET_PRODUCT_VERSION: |
| 2429 | if ( priv->dev_state == DEVICE_STATE_BOOT ){ |
| 2430 | priv->dev_state = DEVICE_STATE_PREINIT; |
| 2431 | } |
| 2432 | break; |
| 2433 | case SME_STOP_REQUEST: |
| 2434 | hostif_stop_request(priv); |
| 2435 | break; |
| 2436 | case SME_RTS_THRESHOLD_REQUEST: |
| 2437 | val = cpu_to_le32((uint32_t)(priv->reg.rts)); |
| 2438 | hostif_mib_set_request(priv, DOT11_RTS_THRESHOLD, |
| 2439 | sizeof(val), MIB_VALUE_TYPE_INT, |
| 2440 | &val ); |
| 2441 | break; |
| 2442 | case SME_FRAGMENTATION_THRESHOLD_REQUEST: |
| 2443 | val = cpu_to_le32((uint32_t)(priv->reg.fragment)); |
| 2444 | hostif_mib_set_request(priv, DOT11_FRAGMENTATION_THRESHOLD, |
| 2445 | sizeof(val), MIB_VALUE_TYPE_INT, |
| 2446 | &val ); |
| 2447 | break; |
| 2448 | case SME_WEP_INDEX_REQUEST: case SME_WEP_KEY1_REQUEST: |
| 2449 | case SME_WEP_KEY2_REQUEST: case SME_WEP_KEY3_REQUEST: |
| 2450 | case SME_WEP_KEY4_REQUEST: case SME_WEP_FLAG_REQUEST: |
| 2451 | hostif_sme_set_wep(priv,event); |
| 2452 | break; |
| 2453 | case SME_RSN_UCAST_REQUEST: case SME_RSN_MCAST_REQUEST: |
| 2454 | case SME_RSN_AUTH_REQUEST: case SME_RSN_ENABLED_REQUEST: |
| 2455 | case SME_RSN_MODE_REQUEST: |
| 2456 | hostif_sme_set_rsn(priv,event); |
| 2457 | break; |
| 2458 | case SME_SET_FLAG: case SME_SET_TXKEY: |
| 2459 | case SME_SET_KEY1: case SME_SET_KEY2: |
| 2460 | case SME_SET_KEY3: case SME_SET_KEY4: |
| 2461 | case SME_SET_PMK_TSC: case SME_SET_GMK1_TSC: |
| 2462 | case SME_SET_GMK2_TSC: |
| 2463 | hostif_sme_set_key(priv,event); |
| 2464 | break; |
| 2465 | case SME_SET_PMKSA: |
| 2466 | hostif_sme_set_pmksa(priv); |
| 2467 | break; |
| 2468 | #ifdef WPS |
| 2469 | case SME_WPS_ENABLE_REQUEST: |
| 2470 | hostif_mib_set_request(priv, LOCAL_WPS_ENABLE, |
| 2471 | sizeof(priv->wps.wps_enabled), |
| 2472 | MIB_VALUE_TYPE_INT, &priv->wps.wps_enabled ); |
| 2473 | break; |
| 2474 | case SME_WPS_PROBE_REQUEST: |
| 2475 | hostif_mib_set_request(priv, LOCAL_WPS_PROBE_REQ, |
| 2476 | priv->wps.ielen, |
| 2477 | MIB_VALUE_TYPE_OSTRING, priv->wps.ie); |
| 2478 | break; |
| 2479 | #endif /* WPS */ |
| 2480 | case SME_MODE_SET_REQUEST: |
| 2481 | hostif_sme_mode_setup(priv); |
| 2482 | break; |
| 2483 | case SME_SET_GAIN: |
| 2484 | hostif_mib_set_request(priv, LOCAL_GAIN, |
| 2485 | sizeof(priv->gain), MIB_VALUE_TYPE_OSTRING, |
| 2486 | &priv->gain); |
| 2487 | break; |
| 2488 | case SME_GET_GAIN: |
| 2489 | hostif_mib_get_request(priv, LOCAL_GAIN); |
| 2490 | break; |
| 2491 | case SME_GET_EEPROM_CKSUM: |
| 2492 | priv->eeprom_checksum = EEPROM_FW_NOT_SUPPORT; /* initialize */ |
| 2493 | hostif_mib_get_request(priv, LOCAL_EEPROM_SUM); |
| 2494 | break; |
| 2495 | case SME_START_REQUEST: |
| 2496 | hostif_start_request( priv, priv->reg.operation_mode ); |
| 2497 | break; |
| 2498 | case SME_START_CONFIRM: |
| 2499 | /* for power save */ |
| 2500 | atomic_set(&priv->psstatus.snooze_guard, 0); |
| 2501 | atomic_set(&priv->psstatus.confirm_wait,0); |
| 2502 | #if !defined(_SDIO_) |
| 2503 | atomic_set(&priv->psstatus.status, PS_NONE); |
| 2504 | #endif |
| 2505 | if ( priv->dev_state == DEVICE_STATE_PREINIT ){ |
| 2506 | priv->dev_state = DEVICE_STATE_INIT; |
| 2507 | } |
| 2508 | /* wake_up_interruptible_all(&priv->confirm_wait); */ |
| 2509 | complete(&priv->confirm_wait); |
| 2510 | break; |
| 2511 | case SME_SLEEP_REQUEST: |
| 2512 | hostif_sme_sleep_set(priv); |
| 2513 | break; |
| 2514 | case SME_SET_REGION: |
| 2515 | val = cpu_to_le32((uint32_t)(priv->region)); |
| 2516 | hostif_mib_set_request(priv, LOCAL_REGION, |
| 2517 | sizeof(val), MIB_VALUE_TYPE_INT, |
| 2518 | &val ); |
| 2519 | break; |
| 2520 | case SME_MULTICAST_CONFIRM: |
| 2521 | case SME_BSS_SCAN_CONFIRM: |
| 2522 | case SME_POW_MNGMT_CONFIRM: |
| 2523 | case SME_PHY_INFO_CONFIRM: |
| 2524 | case SME_STOP_CONFIRM: |
| 2525 | case SME_RTS_THRESHOLD_CONFIRM: |
| 2526 | case SME_FRAGMENTATION_THRESHOLD_CONFIRM: |
| 2527 | case SME_WEP_INDEX_CONFIRM: case SME_WEP_KEY1_CONFIRM: |
| 2528 | case SME_WEP_KEY2_CONFIRM: case SME_WEP_KEY3_CONFIRM: |
| 2529 | case SME_WEP_KEY4_CONFIRM: case SME_WEP_FLAG_CONFIRM: |
| 2530 | case SME_RSN_UCAST_CONFIRM: case SME_RSN_MCAST_CONFIRM: |
| 2531 | case SME_RSN_AUTH_CONFIRM: case SME_RSN_ENABLED_CONFIRM: |
| 2532 | case SME_RSN_MODE_CONFIRM: |
| 2533 | case SME_MODE_SET_CONFIRM: |
| 2534 | break; |
| 2535 | case SME_TERMINATE: |
| 2536 | default: |
| 2537 | break; |
| 2538 | } |
| 2539 | } |
| 2540 | |
| 2541 | static |
| 2542 | void hostif_sme_task( unsigned long dev ) |
| 2543 | { |
| 2544 | ks_wlan_private *priv = (ks_wlan_private *)dev; |
| 2545 | |
| 2546 | DPRINTK(3,"\n"); |
| 2547 | |
| 2548 | if(priv->dev_state >= DEVICE_STATE_BOOT){ |
| 2549 | if (0 < cnt_smeqbody(priv) && priv->dev_state >= DEVICE_STATE_BOOT) { |
| 2550 | hostif_sme_execute(priv, priv->sme_i.event_buff[priv->sme_i.qhead]); |
| 2551 | inc_smeqhead(priv); |
| 2552 | if (0 < cnt_smeqbody(priv)) |
| 2553 | tasklet_schedule(&priv->sme_task); |
| 2554 | } |
| 2555 | } |
| 2556 | return; |
| 2557 | } |
| 2558 | |
| 2559 | /* send to Station Management Entity module */ |
| 2560 | void hostif_sme_enqueue(ks_wlan_private *priv, unsigned short event) |
| 2561 | { |
| 2562 | DPRINTK(3,"\n"); |
| 2563 | |
| 2564 | #if !defined(_SDIO_) |
| 2565 | if(atomic_read(&priv->psstatus.status)==PS_SNOOZE && event < SME_START_CONFIRM){ /* power save wakeup*/ |
| 2566 | schedule_work(&priv->ks_wlan_wakeup_task); |
| 2567 | if(atomic_read(&priv->sme_task.count) <= 0){ |
| 2568 | /* schedule_work(&priv->ks_wlan_wakeup_task); */ |
| 2569 | DPRINTK(4,"sme task disable.\n"); |
| 2570 | tasklet_disable(&priv->sme_task); |
| 2571 | } |
| 2572 | } |
| 2573 | #endif |
| 2574 | |
| 2575 | |
| 2576 | /* enqueue sme event */ |
| 2577 | if (cnt_smeqbody(priv) < (SME_EVENT_BUFF_SIZE - 1)) { |
| 2578 | priv->sme_i.event_buff[priv->sme_i.qtail] = event; |
| 2579 | inc_smeqtail(priv); |
| 2580 | //DPRINTK(3,"inc_smeqtail \n"); |
| 2581 | #ifdef KS_WLAN_DEBUG |
| 2582 | if (priv->sme_i.max_event_count < cnt_smeqbody(priv)) |
| 2583 | priv->sme_i.max_event_count = cnt_smeqbody(priv); |
| 2584 | #endif /* KS_WLAN_DEBUG */ |
| 2585 | } else { |
| 2586 | /* in case of buffer overflow */ |
| 2587 | //DPRINTK(2,"sme queue buffer overflow\n"); |
| 2588 | printk("sme queue buffer overflow\n"); |
| 2589 | } |
| 2590 | |
| 2591 | tasklet_schedule(&priv->sme_task); |
| 2592 | |
| 2593 | } |
| 2594 | |
| 2595 | int hostif_init( ks_wlan_private *priv ) |
| 2596 | { |
| 2597 | int rc=0; |
| 2598 | int i; |
| 2599 | |
| 2600 | DPRINTK(3,"\n"); |
| 2601 | |
| 2602 | priv->aplist.size =0; |
| 2603 | for(i=0;i<LOCAL_APLIST_MAX;i++) |
| 2604 | memset(&(priv->aplist.ap[i]),0,sizeof(struct local_ap_t)); |
| 2605 | priv->infra_status = 0; |
| 2606 | priv->current_rate = 4; |
| 2607 | priv->connect_status = DISCONNECT_STATUS; |
| 2608 | |
| 2609 | spin_lock_init(&priv->multicast_spin); |
| 2610 | |
| 2611 | spin_lock_init(&priv->dev_read_lock); |
| 2612 | init_waitqueue_head (&priv->devread_wait); |
| 2613 | priv->dev_count = 0; |
| 2614 | atomic_set(&priv->event_count, 0); |
| 2615 | atomic_set(&priv->rec_count, 0); |
| 2616 | |
| 2617 | /* for power save */ |
| 2618 | atomic_set(&priv->psstatus.status, PS_NONE); |
| 2619 | atomic_set(&priv->psstatus.confirm_wait, 0); |
| 2620 | atomic_set(&priv->psstatus.snooze_guard, 0); |
| 2621 | /* init_waitqueue_head(&priv->psstatus.wakeup_wait); */ |
| 2622 | init_completion(&priv->psstatus.wakeup_wait); |
| 2623 | //INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task, (void *)priv); |
| 2624 | INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task); |
| 2625 | |
| 2626 | /* WPA */ |
| 2627 | memset(&(priv->wpa), 0, sizeof(priv->wpa)); |
| 2628 | priv->wpa.rsn_enabled = 0; |
| 2629 | priv->wpa.mic_failure.failure = 0; |
| 2630 | priv->wpa.mic_failure.last_failure_time = 0; |
| 2631 | priv->wpa.mic_failure.stop = 0; |
| 2632 | memset(&(priv->pmklist), 0, sizeof(priv->pmklist)); |
| 2633 | INIT_LIST_HEAD(&priv->pmklist.head); |
| 2634 | for(i=0;i<PMK_LIST_MAX;i++) |
| 2635 | INIT_LIST_HEAD(&priv->pmklist.pmk[i].list); |
| 2636 | |
| 2637 | priv->sme_i.sme_status = SME_IDLE; |
| 2638 | priv->sme_i.qhead = priv->sme_i.qtail = 0; |
| 2639 | #ifdef KS_WLAN_DEBUG |
| 2640 | priv->sme_i.max_event_count = 0; |
| 2641 | #endif |
| 2642 | spin_lock_init(&priv->sme_i.sme_spin); |
| 2643 | priv->sme_i.sme_flag = 0; |
| 2644 | |
| 2645 | tasklet_init(&priv->sme_task, hostif_sme_task, (unsigned long)priv); |
| 2646 | |
| 2647 | return rc; |
| 2648 | } |
| 2649 | |
| 2650 | void hostif_exit( ks_wlan_private *priv ) |
| 2651 | { |
| 2652 | tasklet_kill(&priv->sme_task); |
| 2653 | return; |
| 2654 | } |
| 2655 | |