00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 FILE_LICENCE ( BSD3 );
00047
00048 #include <stdlib.h>
00049 #include <gpxe/malloc.h>
00050 #include <gpxe/timer.h>
00051 #include <gpxe/netdevice.h>
00052 #include <gpxe/pci.h>
00053 #include <gpxe/pci_io.h>
00054
00055 #include "base.h"
00056 #include "reg.h"
00057
00058 #define ATH5K_CALIB_INTERVAL 10
00059 #define ATH5K_RETRIES 4
00060 #define ATH5K_DESC_ALIGN 16
00061
00062
00063
00064
00065
00066
00067 static struct pci_device_id ath5k_nics[] = {
00068 PCI_ROM(0x168c, 0x0207, "ath5210e", "Atheros 5210 early", AR5K_AR5210),
00069 PCI_ROM(0x168c, 0x0007, "ath5210", "Atheros 5210", AR5K_AR5210),
00070 PCI_ROM(0x168c, 0x0011, "ath5311", "Atheros 5311 (AHB)", AR5K_AR5211),
00071 PCI_ROM(0x168c, 0x0012, "ath5211", "Atheros 5211", AR5K_AR5211),
00072 PCI_ROM(0x168c, 0x0013, "ath5212", "Atheros 5212", AR5K_AR5212),
00073 PCI_ROM(0xa727, 0x0013, "ath5212c","3com Ath 5212", AR5K_AR5212),
00074 PCI_ROM(0x10b7, 0x0013, "rdag675", "3com 3CRDAG675", AR5K_AR5212),
00075 PCI_ROM(0x168c, 0x1014, "ath5212m", "Ath 5212 miniPCI", AR5K_AR5212),
00076 PCI_ROM(0x168c, 0x0014, "ath5212x14", "Atheros 5212 x14", AR5K_AR5212),
00077 PCI_ROM(0x168c, 0x0015, "ath5212x15", "Atheros 5212 x15", AR5K_AR5212),
00078 PCI_ROM(0x168c, 0x0016, "ath5212x16", "Atheros 5212 x16", AR5K_AR5212),
00079 PCI_ROM(0x168c, 0x0017, "ath5212x17", "Atheros 5212 x17", AR5K_AR5212),
00080 PCI_ROM(0x168c, 0x0018, "ath5212x18", "Atheros 5212 x18", AR5K_AR5212),
00081 PCI_ROM(0x168c, 0x0019, "ath5212x19", "Atheros 5212 x19", AR5K_AR5212),
00082 PCI_ROM(0x168c, 0x001a, "ath2413", "Atheros 2413 Griffin", AR5K_AR5212),
00083 PCI_ROM(0x168c, 0x001b, "ath5413", "Atheros 5413 Eagle", AR5K_AR5212),
00084 PCI_ROM(0x168c, 0x001c, "ath5212e", "Atheros 5212 PCI-E", AR5K_AR5212),
00085 PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212),
00086 };
00087
00088
00089 static const struct ath5k_srev_name srev_names[] = {
00090 { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
00091 { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
00092 { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
00093 { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B },
00094 { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 },
00095 { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 },
00096 { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 },
00097 { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A },
00098 { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 },
00099 { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 },
00100 { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 },
00101 { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 },
00102 { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 },
00103 { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 },
00104 { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 },
00105 { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
00106 { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
00107 { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
00108 { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
00109 { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
00110 { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
00111 { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A },
00112 { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
00113 { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
00114 { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
00115 { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B },
00116 { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
00117 { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
00118 { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
00119 { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
00120 { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
00121 { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
00122 { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
00123 { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
00124 { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
00125 { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
00126 };
00127
00128 #define ATH5K_SPMBL_NO 1
00129 #define ATH5K_SPMBL_YES 2
00130 #define ATH5K_SPMBL_BOTH 3
00131
00132 static const struct {
00133 u16 bitrate;
00134 u8 short_pmbl;
00135 u8 hw_code;
00136 } ath5k_rates[] = {
00137 { 10, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_1M },
00138 { 20, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_2M },
00139 { 55, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_5_5M },
00140 { 110, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_11M },
00141 { 60, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_6M },
00142 { 90, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_9M },
00143 { 120, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_12M },
00144 { 180, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_18M },
00145 { 240, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_24M },
00146 { 360, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_36M },
00147 { 480, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_48M },
00148 { 540, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_54M },
00149 { 20, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE },
00150 { 55, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE },
00151 { 110, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE },
00152 { 0, 0, 0 },
00153 };
00154
00155 #define ATH5K_NR_RATES 15
00156
00157
00158
00159
00160 static int ath5k_probe(struct pci_device *pdev,
00161 const struct pci_device_id *id);
00162 static void ath5k_remove(struct pci_device *pdev);
00163
00164 struct pci_driver ath5k_pci_driver __pci_driver = {
00165 .ids = ath5k_nics,
00166 .id_count = sizeof(ath5k_nics) / sizeof(ath5k_nics[0]),
00167 .probe = ath5k_probe,
00168 .remove = ath5k_remove,
00169 };
00170
00171
00172
00173
00174
00175
00176 static int ath5k_tx(struct net80211_device *dev, struct io_buffer *skb);
00177 static int ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan);
00178 static int ath5k_reset_wake(struct ath5k_softc *sc);
00179 static int ath5k_start(struct net80211_device *dev);
00180 static void ath5k_stop(struct net80211_device *dev);
00181 static int ath5k_config(struct net80211_device *dev, int changed);
00182 static void ath5k_poll(struct net80211_device *dev);
00183 static void ath5k_irq(struct net80211_device *dev, int enable);
00184
00185 static struct net80211_device_operations ath5k_ops = {
00186 .open = ath5k_start,
00187 .close = ath5k_stop,
00188 .transmit = ath5k_tx,
00189 .poll = ath5k_poll,
00190 .irq = ath5k_irq,
00191 .config = ath5k_config,
00192 };
00193
00194
00195
00196
00197
00198 static int ath5k_attach(struct net80211_device *dev);
00199 static void ath5k_detach(struct net80211_device *dev);
00200
00201 static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
00202 struct net80211_channel *channels,
00203 unsigned int mode,
00204 unsigned int max);
00205 static int ath5k_setup_bands(struct net80211_device *dev);
00206 static int ath5k_chan_set(struct ath5k_softc *sc,
00207 struct net80211_channel *chan);
00208 static void ath5k_setcurmode(struct ath5k_softc *sc,
00209 unsigned int mode);
00210 static void ath5k_mode_setup(struct ath5k_softc *sc);
00211
00212
00213 static int ath5k_desc_alloc(struct ath5k_softc *sc);
00214 static void ath5k_desc_free(struct ath5k_softc *sc);
00215
00216 static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
00217 static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
00218
00219 static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
00220 struct ath5k_buf *bf)
00221 {
00222 if (!bf->iob)
00223 return;
00224
00225 net80211_tx_complete(sc->dev, bf->iob, 0, ECANCELED);
00226 bf->iob = NULL;
00227 }
00228
00229 static inline void ath5k_rxbuf_free(struct ath5k_softc *sc __unused,
00230 struct ath5k_buf *bf)
00231 {
00232 free_iob(bf->iob);
00233 bf->iob = NULL;
00234 }
00235
00236
00237 static int ath5k_txq_setup(struct ath5k_softc *sc,
00238 int qtype, int subtype);
00239 static void ath5k_txq_drainq(struct ath5k_softc *sc,
00240 struct ath5k_txq *txq);
00241 static void ath5k_txq_cleanup(struct ath5k_softc *sc);
00242 static void ath5k_txq_release(struct ath5k_softc *sc);
00243
00244 static int ath5k_rx_start(struct ath5k_softc *sc);
00245 static void ath5k_rx_stop(struct ath5k_softc *sc);
00246
00247 static void ath5k_tx_processq(struct ath5k_softc *sc,
00248 struct ath5k_txq *txq);
00249
00250
00251 static int ath5k_init(struct ath5k_softc *sc);
00252 static int ath5k_stop_hw(struct ath5k_softc *sc);
00253
00254 static void ath5k_calibrate(struct ath5k_softc *sc);
00255
00256
00257 static void ath5k_configure_filter(struct ath5k_softc *sc);
00258
00259
00260
00261
00262
00263 #if DBGLVL_MAX
00264 static const char *
00265 ath5k_chip_name(enum ath5k_srev_type type, u16 val)
00266 {
00267 const char *name = "xxxxx";
00268 unsigned int i;
00269
00270 for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
00271 if (srev_names[i].sr_type != type)
00272 continue;
00273
00274 if ((val & 0xf0) == srev_names[i].sr_val)
00275 name = srev_names[i].sr_name;
00276
00277 if ((val & 0xff) == srev_names[i].sr_val) {
00278 name = srev_names[i].sr_name;
00279 break;
00280 }
00281 }
00282
00283 return name;
00284 }
00285 #endif
00286
00287 static int ath5k_probe(struct pci_device *pdev,
00288 const struct pci_device_id *id)
00289 {
00290 void *mem;
00291 struct ath5k_softc *sc;
00292 struct net80211_device *dev;
00293 int ret;
00294 u8 csz;
00295
00296 adjust_pci_device(pdev);
00297
00298
00299
00300
00301
00302 pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
00303 if (csz == 0) {
00304
00305
00306
00307
00308
00309 csz = 16;
00310 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
00311 }
00312
00313
00314
00315
00316
00317 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
00318
00319
00320
00321
00322
00323 pci_write_config_byte(pdev, 0x41, 0);
00324
00325 mem = ioremap(pdev->membase, 0x10000);
00326 if (!mem) {
00327 DBG("ath5k: cannot remap PCI memory region\n");
00328 ret = -EIO;
00329 goto err;
00330 }
00331
00332
00333
00334
00335
00336 dev = net80211_alloc(sizeof(*sc));
00337 if (!dev) {
00338 DBG("ath5k: cannot allocate 802.11 device\n");
00339 ret = -ENOMEM;
00340 goto err_map;
00341 }
00342
00343
00344 sc = dev->priv;
00345 sc->dev = dev;
00346 sc->pdev = pdev;
00347
00348 sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
00349 if (!sc->hwinfo) {
00350 DBG("ath5k: cannot allocate 802.11 hardware info structure\n");
00351 ret = -ENOMEM;
00352 goto err_free;
00353 }
00354
00355 sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
00356 sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
00357 sc->hwinfo->signal_max = 40;
00358 sc->hwinfo->channel_change_time = 5000;
00359
00360
00361 sc->status |= ATH_STAT_INVALID;
00362
00363 sc->iobase = mem;
00364 sc->cachelsz = csz * 4;
00365
00366 DBG("ath5k: register base at %p (%08lx)\n", sc->iobase, pdev->membase);
00367 DBG("ath5k: cache line size %d\n", sc->cachelsz);
00368
00369
00370 pci_set_drvdata(pdev, dev);
00371 dev->netdev->dev = (struct device *)pdev;
00372
00373
00374 ret = ath5k_hw_attach(sc, id->driver_data, &sc->ah);
00375 if (ret)
00376 goto err_free_hwinfo;
00377
00378
00379 ret = ath5k_attach(dev);
00380 if (ret)
00381 goto err_ah;
00382
00383 #if DBGLVL_MAX
00384 DBG("Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
00385 ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
00386 sc->ah->ah_mac_srev, sc->ah->ah_phy_revision);
00387
00388 if (!sc->ah->ah_single_chip) {
00389
00390 if (sc->ah->ah_radio_5ghz_revision &&
00391 !sc->ah->ah_radio_2ghz_revision) {
00392
00393 if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A)) {
00394 DBG("RF%s 2GHz radio found (0x%x)\n",
00395 ath5k_chip_name(AR5K_VERSION_RAD,
00396 sc->ah->ah_radio_5ghz_revision),
00397 sc->ah->ah_radio_5ghz_revision);
00398
00399
00400 } else if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B)) {
00401 DBG("RF%s 5GHz radio found (0x%x)\n",
00402 ath5k_chip_name(AR5K_VERSION_RAD,
00403 sc->ah->ah_radio_5ghz_revision),
00404 sc->ah->ah_radio_5ghz_revision);
00405
00406 } else {
00407 DBG("RF%s multiband radio found (0x%x)\n",
00408 ath5k_chip_name(AR5K_VERSION_RAD,
00409 sc->ah->ah_radio_5ghz_revision),
00410 sc->ah->ah_radio_5ghz_revision);
00411 }
00412 }
00413
00414
00415 else if (sc->ah->ah_radio_5ghz_revision &&
00416 sc->ah->ah_radio_2ghz_revision) {
00417 DBG("RF%s 5GHz radio found (0x%x)\n",
00418 ath5k_chip_name(AR5K_VERSION_RAD,
00419 sc->ah->ah_radio_5ghz_revision),
00420 sc->ah->ah_radio_5ghz_revision);
00421 DBG("RF%s 2GHz radio found (0x%x)\n",
00422 ath5k_chip_name(AR5K_VERSION_RAD,
00423 sc->ah->ah_radio_2ghz_revision),
00424 sc->ah->ah_radio_2ghz_revision);
00425 }
00426 }
00427 #endif
00428
00429
00430 sc->status &= ~ATH_STAT_INVALID;
00431
00432 return 0;
00433 err_ah:
00434 ath5k_hw_detach(sc->ah);
00435 err_free_hwinfo:
00436 free(sc->hwinfo);
00437 err_free:
00438 net80211_free(dev);
00439 err_map:
00440 iounmap(mem);
00441 err:
00442 return ret;
00443 }
00444
00445 static void ath5k_remove(struct pci_device *pdev)
00446 {
00447 struct net80211_device *dev = pci_get_drvdata(pdev);
00448 struct ath5k_softc *sc = dev->priv;
00449
00450 ath5k_detach(dev);
00451 ath5k_hw_detach(sc->ah);
00452 iounmap(sc->iobase);
00453 free(sc->hwinfo);
00454 net80211_free(dev);
00455 }
00456
00457
00458
00459
00460
00461
00462 static int
00463 ath5k_attach(struct net80211_device *dev)
00464 {
00465 struct ath5k_softc *sc = dev->priv;
00466 struct ath5k_hw *ah = sc->ah;
00467 int ret;
00468
00469
00470
00471
00472
00473
00474
00475 ret = ath5k_setup_bands(dev);
00476 if (ret) {
00477 DBG("ath5k: can't get channels\n");
00478 goto err;
00479 }
00480
00481
00482 if (ah->ah_modes & AR5K_MODE_BIT_11A)
00483 ath5k_setcurmode(sc, AR5K_MODE_11A);
00484 else
00485 ath5k_setcurmode(sc, AR5K_MODE_11B);
00486
00487
00488
00489
00490 ret = ath5k_desc_alloc(sc);
00491 if (ret) {
00492 DBG("ath5k: can't allocate descriptors\n");
00493 goto err;
00494 }
00495
00496
00497
00498
00499
00500 ret = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
00501 if (ret) {
00502 DBG("ath5k: can't setup xmit queue\n");
00503 goto err_desc;
00504 }
00505
00506 sc->last_calib_ticks = currticks();
00507
00508 ret = ath5k_eeprom_read_mac(ah, sc->hwinfo->hwaddr);
00509 if (ret) {
00510 DBG("ath5k: unable to read address from EEPROM: 0x%04x\n",
00511 sc->pdev->device);
00512 goto err_queues;
00513 }
00514
00515 memset(sc->bssidmask, 0xff, ETH_ALEN);
00516 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
00517
00518 ret = net80211_register(sc->dev, &ath5k_ops, sc->hwinfo);
00519 if (ret) {
00520 DBG("ath5k: can't register ieee80211 hw\n");
00521 goto err_queues;
00522 }
00523
00524 return 0;
00525 err_queues:
00526 ath5k_txq_release(sc);
00527 err_desc:
00528 ath5k_desc_free(sc);
00529 err:
00530 return ret;
00531 }
00532
00533 static void
00534 ath5k_detach(struct net80211_device *dev)
00535 {
00536 struct ath5k_softc *sc = dev->priv;
00537
00538 net80211_unregister(dev);
00539 ath5k_desc_free(sc);
00540 ath5k_txq_release(sc);
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 static inline short
00554 ath5k_ieee2mhz(short chan)
00555 {
00556 if (chan < 14)
00557 return 2407 + 5 * chan;
00558 if (chan == 14)
00559 return 2484;
00560 if (chan < 27)
00561 return 2212 + 20 * chan;
00562 return 5000 + 5 * chan;
00563 }
00564
00565 static unsigned int
00566 ath5k_copy_channels(struct ath5k_hw *ah,
00567 struct net80211_channel *channels,
00568 unsigned int mode, unsigned int max)
00569 {
00570 unsigned int i, count, size, chfreq, freq, ch;
00571
00572 if (!(ah->ah_modes & (1 << mode)))
00573 return 0;
00574
00575 switch (mode) {
00576 case AR5K_MODE_11A:
00577 case AR5K_MODE_11A_TURBO:
00578
00579 size = 220;
00580 chfreq = CHANNEL_5GHZ;
00581 break;
00582 case AR5K_MODE_11B:
00583 case AR5K_MODE_11G:
00584 case AR5K_MODE_11G_TURBO:
00585 size = 26;
00586 chfreq = CHANNEL_2GHZ;
00587 break;
00588 default:
00589 return 0;
00590 }
00591
00592 for (i = 0, count = 0; i < size && max > 0; i++) {
00593 ch = i + 1 ;
00594 freq = ath5k_ieee2mhz(ch);
00595
00596
00597 if (!ath5k_channel_ok(ah, freq, chfreq))
00598 continue;
00599
00600
00601 channels[count].center_freq = freq;
00602 channels[count].maxpower = 0;
00603 channels[count].band = (chfreq == CHANNEL_2GHZ) ?
00604 NET80211_BAND_2GHZ : NET80211_BAND_5GHZ;
00605 switch (mode) {
00606 case AR5K_MODE_11A:
00607 case AR5K_MODE_11G:
00608 channels[count].hw_value = chfreq | CHANNEL_OFDM;
00609 break;
00610 case AR5K_MODE_11A_TURBO:
00611 case AR5K_MODE_11G_TURBO:
00612 channels[count].hw_value = chfreq |
00613 CHANNEL_OFDM | CHANNEL_TURBO;
00614 break;
00615 case AR5K_MODE_11B:
00616 channels[count].hw_value = CHANNEL_B;
00617 }
00618
00619 count++;
00620 max--;
00621 }
00622
00623 return count;
00624 }
00625
00626 static int
00627 ath5k_setup_bands(struct net80211_device *dev)
00628 {
00629 struct ath5k_softc *sc = dev->priv;
00630 struct ath5k_hw *ah = sc->ah;
00631 int max_c, count_c = 0;
00632 int i;
00633 int band;
00634
00635 max_c = sizeof(sc->hwinfo->channels) / sizeof(sc->hwinfo->channels[0]);
00636
00637
00638 if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11G) {
00639
00640 band = NET80211_BAND_2GHZ;
00641 sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
00642 sc->hwinfo->modes = (NET80211_MODE_G | NET80211_MODE_B);
00643
00644 for (i = 0; i < 12; i++)
00645 sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
00646 sc->hwinfo->nr_rates[band] = 12;
00647
00648 sc->hwinfo->nr_channels =
00649 ath5k_copy_channels(ah, sc->hwinfo->channels,
00650 AR5K_MODE_11G, max_c);
00651 count_c = sc->hwinfo->nr_channels;
00652 max_c -= count_c;
00653 } else if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B) {
00654
00655 band = NET80211_BAND_2GHZ;
00656 sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
00657 sc->hwinfo->modes = NET80211_MODE_B;
00658
00659 for (i = 0; i < 4; i++)
00660 sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
00661 sc->hwinfo->nr_rates[band] = 4;
00662
00663 sc->hwinfo->nr_channels =
00664 ath5k_copy_channels(ah, sc->hwinfo->channels,
00665 AR5K_MODE_11B, max_c);
00666 count_c = sc->hwinfo->nr_channels;
00667 max_c -= count_c;
00668 }
00669
00670
00671 if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A) {
00672 band = NET80211_BAND_5GHZ;
00673 sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
00674 sc->hwinfo->modes |= NET80211_MODE_A;
00675
00676 for (i = 0; i < 8; i++)
00677 sc->hwinfo->rates[band][i] = ath5k_rates[i+4].bitrate;
00678 sc->hwinfo->nr_rates[band] = 8;
00679
00680 sc->hwinfo->nr_channels =
00681 ath5k_copy_channels(ah, sc->hwinfo->channels,
00682 AR5K_MODE_11B, max_c);
00683 count_c = sc->hwinfo->nr_channels;
00684 max_c -= count_c;
00685 }
00686
00687 return 0;
00688 }
00689
00690
00691
00692
00693
00694
00695
00696 static int
00697 ath5k_chan_set(struct ath5k_softc *sc, struct net80211_channel *chan)
00698 {
00699 if (chan->center_freq != sc->curchan->center_freq ||
00700 chan->hw_value != sc->curchan->hw_value) {
00701
00702
00703
00704
00705
00706
00707 DBG2("ath5k: resetting for channel change (%d -> %d MHz)\n",
00708 sc->curchan->center_freq, chan->center_freq);
00709 return ath5k_reset(sc, chan);
00710 }
00711
00712 return 0;
00713 }
00714
00715 static void
00716 ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
00717 {
00718 sc->curmode = mode;
00719
00720 if (mode == AR5K_MODE_11A) {
00721 sc->curband = NET80211_BAND_5GHZ;
00722 } else {
00723 sc->curband = NET80211_BAND_2GHZ;
00724 }
00725 }
00726
00727 static void
00728 ath5k_mode_setup(struct ath5k_softc *sc)
00729 {
00730 struct ath5k_hw *ah = sc->ah;
00731 u32 rfilt;
00732
00733
00734 rfilt = sc->filter_flags;
00735 ath5k_hw_set_rx_filter(ah, rfilt);
00736
00737 if (ath5k_hw_hasbssidmask(ah))
00738 ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
00739
00740
00741 ath5k_hw_set_opmode(ah);
00742
00743 ath5k_hw_set_mcast_filter(ah, 0, 0);
00744 }
00745
00746 static inline int
00747 ath5k_hw_rix_to_bitrate(int hw_rix)
00748 {
00749 int i;
00750
00751 for (i = 0; i < ATH5K_NR_RATES; i++) {
00752 if (ath5k_rates[i].hw_code == hw_rix)
00753 return ath5k_rates[i].bitrate;
00754 }
00755
00756 DBG("ath5k: invalid rix %02x\n", hw_rix);
00757 return 10;
00758 }
00759
00760 int ath5k_bitrate_to_hw_rix(int bitrate)
00761 {
00762 int i;
00763
00764 for (i = 0; i < ATH5K_NR_RATES; i++) {
00765 if (ath5k_rates[i].bitrate == bitrate)
00766 return ath5k_rates[i].hw_code;
00767 }
00768
00769 DBG("ath5k: invalid bitrate %d\n", bitrate);
00770 return ATH5K_RATE_CODE_1M;
00771 }
00772
00773
00774
00775
00776
00777 static struct io_buffer *
00778 ath5k_rx_iob_alloc(struct ath5k_softc *sc, u32 *iob_addr)
00779 {
00780 struct io_buffer *iob;
00781 unsigned int off;
00782
00783
00784
00785
00786
00787 iob = alloc_iob(sc->rxbufsize + sc->cachelsz - 1);
00788
00789 if (!iob) {
00790 DBG("ath5k: can't alloc iobuf of size %d\n",
00791 sc->rxbufsize + sc->cachelsz - 1);
00792 return NULL;
00793 }
00794
00795 *iob_addr = virt_to_bus(iob->data);
00796
00797
00798
00799
00800
00801
00802 off = *iob_addr % sc->cachelsz;
00803 if (off != 0) {
00804 iob_reserve(iob, sc->cachelsz - off);
00805 *iob_addr += sc->cachelsz - off;
00806 }
00807
00808 return iob;
00809 }
00810
00811 static int
00812 ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
00813 {
00814 struct ath5k_hw *ah = sc->ah;
00815 struct io_buffer *iob = bf->iob;
00816 struct ath5k_desc *ds;
00817
00818 if (!iob) {
00819 iob = ath5k_rx_iob_alloc(sc, &bf->iobaddr);
00820 if (!iob)
00821 return -ENOMEM;
00822 bf->iob = iob;
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 ds = bf->desc;
00841 ds->ds_link = bf->daddr;
00842 ds->ds_data = bf->iobaddr;
00843 if (ah->ah_setup_rx_desc(ah, ds,
00844 iob_tailroom(iob),
00845 0) != 0) {
00846 DBG("ath5k: error setting up RX descriptor for %d bytes\n", iob_tailroom(iob));
00847 return -EINVAL;
00848 }
00849
00850 if (sc->rxlink != NULL)
00851 *sc->rxlink = bf->daddr;
00852 sc->rxlink = &ds->ds_link;
00853 return 0;
00854 }
00855
00856 static int
00857 ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
00858 {
00859 struct ath5k_hw *ah = sc->ah;
00860 struct ath5k_txq *txq = &sc->txq;
00861 struct ath5k_desc *ds = bf->desc;
00862 struct io_buffer *iob = bf->iob;
00863 unsigned int pktlen, flags;
00864 int ret;
00865 u16 duration = 0;
00866 u16 cts_rate = 0;
00867
00868 flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
00869 bf->iobaddr = virt_to_bus(iob->data);
00870 pktlen = iob_len(iob);
00871
00872
00873
00874
00875 if (sc->dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
00876 struct net80211_device *dev = sc->dev;
00877
00878 flags |= AR5K_TXDESC_CTSENA;
00879 cts_rate = sc->hw_rtscts_rate;
00880 duration = net80211_cts_duration(dev, pktlen);
00881 }
00882 ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
00883 IEEE80211_TYP_FRAME_HEADER_LEN,
00884 AR5K_PKT_TYPE_NORMAL, sc->power_level * 2,
00885 sc->hw_rate, ATH5K_RETRIES,
00886 AR5K_TXKEYIX_INVALID, 0, flags,
00887 cts_rate, duration);
00888 if (ret)
00889 return ret;
00890
00891 ds->ds_link = 0;
00892 ds->ds_data = bf->iobaddr;
00893
00894 list_add_tail(&bf->list, &txq->q);
00895 if (txq->link == NULL)
00896 ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
00897 else
00898 *txq->link = bf->daddr;
00899
00900 txq->link = &ds->ds_link;
00901 ath5k_hw_start_tx_dma(ah, txq->qnum);
00902 mb();
00903
00904 return 0;
00905 }
00906
00907
00908
00909
00910
00911 static int
00912 ath5k_desc_alloc(struct ath5k_softc *sc)
00913 {
00914 struct ath5k_desc *ds;
00915 struct ath5k_buf *bf;
00916 u32 da;
00917 unsigned int i;
00918 int ret;
00919
00920
00921 sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + 1);
00922 sc->desc = malloc_dma(sc->desc_len, ATH5K_DESC_ALIGN);
00923 if (sc->desc == NULL) {
00924 DBG("ath5k: can't allocate descriptors\n");
00925 ret = -ENOMEM;
00926 goto err;
00927 }
00928 memset(sc->desc, 0, sc->desc_len);
00929 sc->desc_daddr = virt_to_bus(sc->desc);
00930
00931 ds = sc->desc;
00932 da = sc->desc_daddr;
00933
00934 bf = calloc(ATH_TXBUF + ATH_RXBUF + 1, sizeof(struct ath5k_buf));
00935 if (bf == NULL) {
00936 DBG("ath5k: can't allocate buffer pointers\n");
00937 ret = -ENOMEM;
00938 goto err_free;
00939 }
00940 sc->bufptr = bf;
00941
00942 INIT_LIST_HEAD(&sc->rxbuf);
00943 for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
00944 bf->desc = ds;
00945 bf->daddr = da;
00946 list_add_tail(&bf->list, &sc->rxbuf);
00947 }
00948
00949 INIT_LIST_HEAD(&sc->txbuf);
00950 sc->txbuf_len = ATH_TXBUF;
00951 for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
00952 bf->desc = ds;
00953 bf->daddr = da;
00954 list_add_tail(&bf->list, &sc->txbuf);
00955 }
00956
00957 return 0;
00958
00959 err_free:
00960 free_dma(sc->desc, sc->desc_len);
00961 err:
00962 sc->desc = NULL;
00963 return ret;
00964 }
00965
00966 static void
00967 ath5k_desc_free(struct ath5k_softc *sc)
00968 {
00969 struct ath5k_buf *bf;
00970
00971 list_for_each_entry(bf, &sc->txbuf, list)
00972 ath5k_txbuf_free(sc, bf);
00973 list_for_each_entry(bf, &sc->rxbuf, list)
00974 ath5k_rxbuf_free(sc, bf);
00975
00976
00977 free_dma(sc->desc, sc->desc_len);
00978
00979 free(sc->bufptr);
00980 sc->bufptr = NULL;
00981 }
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 static int
00992 ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype)
00993 {
00994 struct ath5k_hw *ah = sc->ah;
00995 struct ath5k_txq *txq;
00996 struct ath5k_txq_info qi = {
00997 .tqi_subtype = subtype,
00998 .tqi_aifs = AR5K_TXQ_USEDEFAULT,
00999 .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
01000 .tqi_cw_max = AR5K_TXQ_USEDEFAULT
01001 };
01002 int qnum;
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
01017 AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
01018 qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
01019 if (qnum < 0) {
01020 DBG("ath5k: can't set up a TX queue\n");
01021 return -EIO;
01022 }
01023
01024 txq = &sc->txq;
01025 if (!txq->setup) {
01026 txq->qnum = qnum;
01027 txq->link = NULL;
01028 INIT_LIST_HEAD(&txq->q);
01029 txq->setup = 1;
01030 }
01031 return 0;
01032 }
01033
01034 static void
01035 ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
01036 {
01037 struct ath5k_buf *bf, *bf0;
01038
01039 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
01040 ath5k_txbuf_free(sc, bf);
01041
01042 list_del(&bf->list);
01043 list_add_tail(&bf->list, &sc->txbuf);
01044 sc->txbuf_len++;
01045 }
01046 txq->link = NULL;
01047 }
01048
01049
01050
01051
01052 static void
01053 ath5k_txq_cleanup(struct ath5k_softc *sc)
01054 {
01055 struct ath5k_hw *ah = sc->ah;
01056
01057 if (!(sc->status & ATH_STAT_INVALID)) {
01058
01059 if (sc->txq.setup) {
01060 ath5k_hw_stop_tx_dma(ah, sc->txq.qnum);
01061 DBG("ath5k: txq [%d] %x, link %p\n",
01062 sc->txq.qnum,
01063 ath5k_hw_get_txdp(ah, sc->txq.qnum),
01064 sc->txq.link);
01065 }
01066 }
01067
01068 if (sc->txq.setup)
01069 ath5k_txq_drainq(sc, &sc->txq);
01070 }
01071
01072 static void
01073 ath5k_txq_release(struct ath5k_softc *sc)
01074 {
01075 if (sc->txq.setup) {
01076 ath5k_hw_release_tx_queue(sc->ah);
01077 sc->txq.setup = 0;
01078 }
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 static int
01092 ath5k_rx_start(struct ath5k_softc *sc)
01093 {
01094 struct ath5k_hw *ah = sc->ah;
01095 struct ath5k_buf *bf;
01096 int ret;
01097
01098 sc->rxbufsize = IEEE80211_MAX_LEN;
01099 if (sc->rxbufsize % sc->cachelsz != 0)
01100 sc->rxbufsize += sc->cachelsz - (sc->rxbufsize % sc->cachelsz);
01101
01102 sc->rxlink = NULL;
01103
01104 list_for_each_entry(bf, &sc->rxbuf, list) {
01105 ret = ath5k_rxbuf_setup(sc, bf);
01106 if (ret != 0)
01107 return ret;
01108 }
01109
01110 bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
01111
01112 ath5k_hw_set_rxdp(ah, bf->daddr);
01113 ath5k_hw_start_rx_dma(ah);
01114 ath5k_mode_setup(sc);
01115 ath5k_hw_start_rx_pcu(ah);
01116
01117 return 0;
01118 }
01119
01120
01121
01122
01123 static void
01124 ath5k_rx_stop(struct ath5k_softc *sc)
01125 {
01126 struct ath5k_hw *ah = sc->ah;
01127
01128 ath5k_hw_stop_rx_pcu(ah);
01129 ath5k_hw_set_rx_filter(ah, 0);
01130 ath5k_hw_stop_rx_dma(ah);
01131
01132 sc->rxlink = NULL;
01133 }
01134
01135 static void
01136 ath5k_handle_rx(struct ath5k_softc *sc)
01137 {
01138 struct ath5k_rx_status rs;
01139 struct io_buffer *iob, *next_iob;
01140 u32 next_iob_addr;
01141 struct ath5k_buf *bf, *bf_last;
01142 struct ath5k_desc *ds;
01143 int ret;
01144
01145 memset(&rs, 0, sizeof(rs));
01146
01147 if (list_empty(&sc->rxbuf)) {
01148 DBG("ath5k: empty rx buf pool\n");
01149 return;
01150 }
01151
01152 bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
01153
01154 do {
01155 bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
01156 assert(bf->iob != NULL);
01157 iob = bf->iob;
01158 ds = bf->desc;
01159
01160
01161
01162
01163
01164
01165 if (bf_last == bf)
01166 bf->flags |= 1;
01167 if (bf->flags) {
01168 struct ath5k_buf *bf_next = list_entry(bf->list.next,
01169 struct ath5k_buf, list);
01170 ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
01171 &rs);
01172 if (ret)
01173 break;
01174 bf->flags &= ~1;
01175
01176 goto next;
01177 }
01178
01179 ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
01180 if (ret) {
01181 if (ret != -EINPROGRESS) {
01182 DBG("ath5k: error in processing rx desc: %s\n",
01183 strerror(ret));
01184 net80211_rx_err(sc->dev, NULL, -ret);
01185 } else {
01186
01187
01188 }
01189 return;
01190 }
01191
01192 if (rs.rs_more) {
01193 DBG("ath5k: unsupported fragmented rx\n");
01194 goto next;
01195 }
01196
01197 if (rs.rs_status) {
01198 if (rs.rs_status & AR5K_RXERR_PHY) {
01199
01200 net80211_rx_err(sc->dev, NULL, EIO);
01201 goto next;
01202 }
01203 if (rs.rs_status & AR5K_RXERR_CRC) {
01204
01205 goto next;
01206 }
01207 if (rs.rs_status & AR5K_RXERR_DECRYPT) {
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
01219 !(rs.rs_status & AR5K_RXERR_CRC))
01220 goto accept;
01221 }
01222
01223
01224 DBG("ath5k: packet rx status %x\n", rs.rs_status);
01225 goto next;
01226 }
01227 accept:
01228 next_iob = ath5k_rx_iob_alloc(sc, &next_iob_addr);
01229
01230
01231
01232
01233
01234 if (!next_iob) {
01235 DBG("ath5k: dropping packet under memory pressure\n");
01236 goto next;
01237 }
01238
01239 iob_put(iob, rs.rs_datalen);
01240
01241
01242
01243
01244
01245
01246
01247 DBG2("ath5k: rx %d bytes, signal %d\n", rs.rs_datalen,
01248 rs.rs_rssi);
01249
01250 net80211_rx(sc->dev, iob, rs.rs_rssi,
01251 ath5k_hw_rix_to_bitrate(rs.rs_rate));
01252
01253 bf->iob = next_iob;
01254 bf->iobaddr = next_iob_addr;
01255 next:
01256 list_del(&bf->list);
01257 list_add_tail(&bf->list, &sc->rxbuf);
01258 } while (ath5k_rxbuf_setup(sc, bf) == 0);
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268 static void
01269 ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
01270 {
01271 struct ath5k_tx_status ts;
01272 struct ath5k_buf *bf, *bf0;
01273 struct ath5k_desc *ds;
01274 struct io_buffer *iob;
01275 int ret;
01276
01277 memset(&ts, 0, sizeof(ts));
01278
01279 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
01280 ds = bf->desc;
01281
01282 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
01283 if (ret) {
01284 if (ret != -EINPROGRESS) {
01285 DBG("ath5k: error in processing tx desc: %s\n",
01286 strerror(ret));
01287 } else {
01288
01289 }
01290 break;
01291 }
01292
01293 iob = bf->iob;
01294 bf->iob = NULL;
01295
01296 DBG2("ath5k: tx %d bytes complete, %d retries\n",
01297 iob_len(iob), ts.ts_retry[0]);
01298
01299 net80211_tx_complete(sc->dev, iob, ts.ts_retry[0],
01300 ts.ts_status ? EIO : 0);
01301
01302 list_del(&bf->list);
01303 list_add_tail(&bf->list, &sc->txbuf);
01304 sc->txbuf_len++;
01305 }
01306
01307 if (list_empty(&txq->q))
01308 txq->link = NULL;
01309 }
01310
01311 static void
01312 ath5k_handle_tx(struct ath5k_softc *sc)
01313 {
01314 ath5k_tx_processq(sc, &sc->txq);
01315 }
01316
01317
01318
01319
01320
01321
01322 static void
01323 ath5k_irq(struct net80211_device *dev, int enable)
01324 {
01325 struct ath5k_softc *sc = dev->priv;
01326 struct ath5k_hw *ah = sc->ah;
01327
01328 sc->irq_ena = enable;
01329 ah->ah_ier = enable ? AR5K_IER_ENABLE : AR5K_IER_DISABLE;
01330
01331 ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
01332 ath5k_hw_set_imr(ah, sc->imask);
01333 }
01334
01335 static int
01336 ath5k_init(struct ath5k_softc *sc)
01337 {
01338 struct ath5k_hw *ah = sc->ah;
01339 int ret, i;
01340
01341
01342
01343
01344
01345 ath5k_stop_hw(sc);
01346
01347
01348
01349
01350
01351
01352
01353
01354 sc->curchan = sc->dev->channels + sc->dev->channel;
01355 sc->curband = sc->curchan->band;
01356 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
01357 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
01358 AR5K_INT_FATAL | AR5K_INT_GLOBAL;
01359 ret = ath5k_reset(sc, NULL);
01360 if (ret)
01361 goto done;
01362
01363 ath5k_rfkill_hw_start(ah);
01364
01365
01366
01367
01368
01369 for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
01370 ath5k_hw_reset_key(ah, i);
01371
01372
01373 ath5k_hw_set_ack_bitrate_high(ah, 0);
01374
01375 ret = 0;
01376 done:
01377 mb();
01378 return ret;
01379 }
01380
01381 static int
01382 ath5k_stop_hw(struct ath5k_softc *sc)
01383 {
01384 struct ath5k_hw *ah = sc->ah;
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 if (!(sc->status & ATH_STAT_INVALID)) {
01403 ath5k_hw_set_imr(ah, 0);
01404 }
01405 ath5k_txq_cleanup(sc);
01406 if (!(sc->status & ATH_STAT_INVALID)) {
01407 ath5k_rx_stop(sc);
01408 ath5k_hw_phy_disable(ah);
01409 } else
01410 sc->rxlink = NULL;
01411
01412 ath5k_rfkill_hw_stop(sc->ah);
01413
01414 return 0;
01415 }
01416
01417 static void
01418 ath5k_poll(struct net80211_device *dev)
01419 {
01420 struct ath5k_softc *sc = dev->priv;
01421 struct ath5k_hw *ah = sc->ah;
01422 enum ath5k_int status;
01423 unsigned int counter = 1000;
01424
01425 if (currticks() - sc->last_calib_ticks >
01426 ATH5K_CALIB_INTERVAL * ticks_per_sec()) {
01427 ath5k_calibrate(sc);
01428 sc->last_calib_ticks = currticks();
01429 }
01430
01431 if ((sc->status & ATH_STAT_INVALID) ||
01432 (sc->irq_ena && !ath5k_hw_is_intr_pending(ah)))
01433 return;
01434
01435 do {
01436 ath5k_hw_get_isr(ah, &status);
01437 DBGP("ath5k: status %#x/%#x\n", status, sc->imask);
01438 if (status & AR5K_INT_FATAL) {
01439
01440
01441
01442
01443 DBG("ath5k: fatal error, resetting\n");
01444 ath5k_reset_wake(sc);
01445 } else if (status & AR5K_INT_RXORN) {
01446 DBG("ath5k: rx overrun, resetting\n");
01447 ath5k_reset_wake(sc);
01448 } else {
01449 if (status & AR5K_INT_RXEOL) {
01450
01451
01452
01453
01454
01455 DBG("ath5k: rx EOL\n");
01456 sc->rxlink = NULL;
01457 }
01458 if (status & AR5K_INT_TXURN) {
01459
01460 DBG("ath5k: tx underrun\n");
01461 ath5k_hw_update_tx_triglevel(ah, 1);
01462 }
01463 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
01464 ath5k_handle_rx(sc);
01465 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
01466 | AR5K_INT_TXERR | AR5K_INT_TXEOL))
01467 ath5k_handle_tx(sc);
01468 }
01469 } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
01470
01471 if (!counter)
01472 DBG("ath5k: too many interrupts, giving up for now\n");
01473 }
01474
01475
01476
01477
01478
01479 static void
01480 ath5k_calibrate(struct ath5k_softc *sc)
01481 {
01482 struct ath5k_hw *ah = sc->ah;
01483
01484 if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
01485
01486
01487
01488
01489 DBG("ath5k: resetting for calibration\n");
01490 ath5k_reset_wake(sc);
01491 }
01492 if (ath5k_hw_phy_calibrate(ah, sc->curchan))
01493 DBG("ath5k: calibration of channel %d failed\n",
01494 sc->curchan->channel_nr);
01495 }
01496
01497
01498
01499
01500
01501
01502 static int
01503 ath5k_tx(struct net80211_device *dev, struct io_buffer *iob)
01504 {
01505 struct ath5k_softc *sc = dev->priv;
01506 struct ath5k_buf *bf;
01507 int rc;
01508
01509
01510
01511
01512
01513
01514 if (list_empty(&sc->txbuf)) {
01515 DBG("ath5k: dropping packet because no tx bufs available\n");
01516 return -ENOBUFS;
01517 }
01518
01519 bf = list_entry(sc->txbuf.next, struct ath5k_buf, list);
01520 list_del(&bf->list);
01521 sc->txbuf_len--;
01522
01523 bf->iob = iob;
01524
01525 if ((rc = ath5k_txbuf_setup(sc, bf)) != 0) {
01526 bf->iob = NULL;
01527 list_add_tail(&bf->list, &sc->txbuf);
01528 sc->txbuf_len++;
01529 return rc;
01530 }
01531 return 0;
01532 }
01533
01534
01535
01536
01537
01538 static int
01539 ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan)
01540 {
01541 struct ath5k_hw *ah = sc->ah;
01542 int ret;
01543
01544 if (chan) {
01545 ath5k_hw_set_imr(ah, 0);
01546 ath5k_txq_cleanup(sc);
01547 ath5k_rx_stop(sc);
01548
01549 sc->curchan = chan;
01550 sc->curband = chan->band;
01551 }
01552
01553 ret = ath5k_hw_reset(ah, sc->curchan, 1);
01554 if (ret) {
01555 DBG("ath5k: can't reset hardware: %s\n", strerror(ret));
01556 return ret;
01557 }
01558
01559 ret = ath5k_rx_start(sc);
01560 if (ret) {
01561 DBG("ath5k: can't start rx logic: %s\n", strerror(ret));
01562 return ret;
01563 }
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 ath5k_irq(sc->dev, sc->irq_ena);
01578
01579 return 0;
01580 }
01581
01582 static int ath5k_reset_wake(struct ath5k_softc *sc)
01583 {
01584 return ath5k_reset(sc, sc->curchan);
01585 }
01586
01587 static int ath5k_start(struct net80211_device *dev)
01588 {
01589 struct ath5k_softc *sc = dev->priv;
01590 int ret;
01591
01592 if ((ret = ath5k_init(sc)) != 0)
01593 return ret;
01594
01595 sc->assoc = 0;
01596 ath5k_configure_filter(sc);
01597 ath5k_hw_set_lladdr(sc->ah, dev->netdev->ll_addr);
01598
01599 return 0;
01600 }
01601
01602 static void ath5k_stop(struct net80211_device *dev)
01603 {
01604 struct ath5k_softc *sc = dev->priv;
01605 u8 mac[ETH_ALEN] = {};
01606
01607 ath5k_hw_set_lladdr(sc->ah, mac);
01608
01609 ath5k_stop_hw(sc);
01610 }
01611
01612 static int
01613 ath5k_config(struct net80211_device *dev, int changed)
01614 {
01615 struct ath5k_softc *sc = dev->priv;
01616 struct ath5k_hw *ah = sc->ah;
01617 struct net80211_channel *chan = &dev->channels[dev->channel];
01618 int ret;
01619
01620 if (changed & NET80211_CFG_CHANNEL) {
01621 sc->power_level = chan->maxpower;
01622 if ((ret = ath5k_chan_set(sc, chan)) != 0)
01623 return ret;
01624 }
01625
01626 if ((changed & NET80211_CFG_RATE) ||
01627 (changed & NET80211_CFG_PHY_PARAMS)) {
01628 int spmbl = ATH5K_SPMBL_NO;
01629 u16 rate = dev->rates[dev->rate];
01630 u16 slowrate = dev->rates[dev->rtscts_rate];
01631 int i;
01632
01633 if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
01634 spmbl = ATH5K_SPMBL_YES;
01635
01636 for (i = 0; i < ATH5K_NR_RATES; i++) {
01637 if (ath5k_rates[i].bitrate == rate &&
01638 (ath5k_rates[i].short_pmbl & spmbl))
01639 sc->hw_rate = ath5k_rates[i].hw_code;
01640
01641 if (ath5k_rates[i].bitrate == slowrate &&
01642 (ath5k_rates[i].short_pmbl & spmbl))
01643 sc->hw_rtscts_rate = ath5k_rates[i].hw_code;
01644 }
01645 }
01646
01647 if (changed & NET80211_CFG_ASSOC) {
01648 sc->assoc = !!(dev->state & NET80211_ASSOCIATED);
01649 if (sc->assoc) {
01650 memcpy(ah->ah_bssid, dev->bssid, ETH_ALEN);
01651 } else {
01652 memset(ah->ah_bssid, 0xff, ETH_ALEN);
01653 }
01654 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
01655 }
01656
01657 return 0;
01658 }
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678 static void ath5k_configure_filter(struct ath5k_softc *sc)
01679 {
01680 struct ath5k_hw *ah = sc->ah;
01681 u32 mfilt[2], rfilt;
01682
01683
01684 mfilt[0] = ~0;
01685 mfilt[1] = ~0;
01686
01687
01688 rfilt = (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
01689 AR5K_RX_FILTER_MCAST | AR5K_RX_FILTER_BEACON);
01690
01691
01692 ath5k_hw_set_rx_filter(ah, rfilt);
01693
01694
01695 ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
01696
01697
01698
01699 sc->filter_flags = rfilt;
01700 }