|
|
1.1 ! root 1: ! 2: /* ! 3: * Linux device driver for RTL8180 / RTL8185 ! 4: * ! 5: * Copyright 2007 Michael Wu <[email protected]> ! 6: * Copyright 2007 Andrea Merello <[email protected]> ! 7: * ! 8: * Modified for iPXE, June 2009, by Joshua Oreman <[email protected]> ! 9: * ! 10: * Based on the r8180 driver, which is: ! 11: * Copyright 2004-2005 Andrea Merello <[email protected]>, et al. ! 12: * ! 13: * Thanks to Realtek for their support! ! 14: * ! 15: * This program is free software; you can redistribute it and/or modify ! 16: * it under the terms of the GNU General Public License version 2 as ! 17: * published by the Free Software Foundation. ! 18: */ ! 19: ! 20: FILE_LICENCE(GPL2_ONLY); ! 21: ! 22: #include <stdint.h> ! 23: #include <errno.h> ! 24: #include <stdio.h> ! 25: #include <unistd.h> ! 26: #include <byteswap.h> ! 27: #include <ipxe/iobuf.h> ! 28: #include <ipxe/malloc.h> ! 29: #include <ipxe/pci.h> ! 30: #include <ipxe/net80211.h> ! 31: #include <ipxe/netdevice.h> ! 32: #include <ipxe/threewire.h> ! 33: ! 34: #include "rtl818x.h" ! 35: ! 36: /* rtl818x_rates[hw rate number] = rate in 100kbps units */ ! 37: static const u16 rtl818x_rates[] = { ! 38: 10, 20, 55, 110, /* 802.11b */ ! 39: 60, 90, 120, 180, 240, 360, 480, 540, /* 802.11g */ ! 40: 0, 0, 0, 0, /* index safely using a value masked with 0xF */ ! 41: }; ! 42: #define RTL818X_NR_B_RATES 4 ! 43: #define RTL818X_NR_RATES 12 ! 44: ! 45: /* used by RF drivers */ ! 46: void rtl818x_write_phy(struct net80211_device *dev, u8 addr, u32 data) ! 47: { ! 48: struct rtl818x_priv *priv = dev->priv; ! 49: int i = 10; ! 50: u32 buf; ! 51: ! 52: buf = (data << 8) | addr; ! 53: ! 54: rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf | 0x80); ! 55: while (i--) { ! 56: rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf); ! 57: if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF)) ! 58: return; ! 59: } ! 60: } ! 61: ! 62: static void rtl818x_handle_rx(struct net80211_device *dev) ! 63: { ! 64: struct rtl818x_priv *priv = dev->priv; ! 65: unsigned int count = RTL818X_RX_RING_SIZE; ! 66: ! 67: while (count--) { ! 68: struct rtl818x_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; ! 69: struct io_buffer *iob = priv->rx_buf[priv->rx_idx]; ! 70: u32 flags = le32_to_cpu(entry->flags); ! 71: ! 72: if (flags & RTL818X_RX_DESC_FLAG_OWN) ! 73: return; ! 74: ! 75: if (flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | ! 76: RTL818X_RX_DESC_FLAG_FOF | ! 77: RTL818X_RX_DESC_FLAG_RX_ERR)) { ! 78: /* This is crappy hardware. The Linux driver ! 79: doesn't even log these. */ ! 80: goto done; ! 81: } else if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) { ! 82: /* This is actually a corrupt packet. */ ! 83: DBG2("rtl818x RX:%d CRC fail: flags %08x\n", ! 84: priv->rx_idx, flags); ! 85: net80211_rx_err(dev, NULL, EIO); ! 86: } else { ! 87: u32 flags2 = le32_to_cpu(entry->flags2); ! 88: struct io_buffer *new_iob = alloc_iob(MAX_RX_SIZE); ! 89: if (!new_iob) { ! 90: net80211_rx_err(dev, NULL, ENOMEM); ! 91: goto done; ! 92: } ! 93: ! 94: DBGP("rtl818x RX:%d success: flags %08x %08x\n", ! 95: priv->rx_idx, flags, flags2); ! 96: ! 97: iob_put(iob, flags & 0xFFF); ! 98: ! 99: net80211_rx(dev, iob, (flags2 >> 8) & 0x7f, ! 100: rtl818x_rates[(flags >> 20) & 0xf]); ! 101: ! 102: iob = new_iob; ! 103: priv->rx_buf[priv->rx_idx] = iob; ! 104: } ! 105: ! 106: done: ! 107: entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data)); ! 108: entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | MAX_RX_SIZE); ! 109: ! 110: if (priv->rx_idx == RTL818X_RX_RING_SIZE - 1) ! 111: entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); ! 112: ! 113: priv->rx_idx = (priv->rx_idx + 1) % RTL818X_RX_RING_SIZE; ! 114: } ! 115: } ! 116: ! 117: static void rtl818x_handle_tx(struct net80211_device *dev) ! 118: { ! 119: struct rtl818x_priv *priv = dev->priv; ! 120: unsigned int count = RTL818X_TX_RING_SIZE; ! 121: ! 122: while (count--) { ! 123: struct rtl818x_tx_desc *entry = &priv->tx_ring[priv->tx_cons]; ! 124: struct io_buffer *iob = priv->tx_buf[priv->tx_cons]; ! 125: u32 flags = le32_to_cpu(entry->flags); ! 126: int rc; ! 127: ! 128: if ((flags & RTL818X_TX_DESC_FLAG_OWN) || !iob) ! 129: return; ! 130: ! 131: rc = 0; ! 132: if (!(flags & RTL818X_TX_DESC_FLAG_TX_OK)) { ! 133: /* our packet was not ACKed properly */ ! 134: rc = EIO; ! 135: } ! 136: ! 137: net80211_tx_complete(dev, iob, flags & 0xFF, rc); ! 138: ! 139: priv->tx_buf[priv->tx_cons] = NULL; ! 140: priv->tx_cons = (priv->tx_cons + 1) % RTL818X_TX_RING_SIZE; ! 141: } ! 142: } ! 143: ! 144: static void rtl818x_poll(struct net80211_device *dev) ! 145: { ! 146: struct rtl818x_priv *priv = dev->priv; ! 147: u16 reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); ! 148: ! 149: if (reg == 0xFFFF) ! 150: return; ! 151: ! 152: rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); ! 153: ! 154: if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) ! 155: rtl818x_handle_tx(dev); ! 156: ! 157: if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) ! 158: rtl818x_handle_rx(dev); ! 159: } ! 160: ! 161: #define DIV_ROUND_UP(n,d) (((n)+(d)-1)/(d)) ! 162: ! 163: static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob) ! 164: { ! 165: struct rtl818x_priv *priv = dev->priv; ! 166: struct rtl818x_tx_desc *entry; ! 167: u32 tx_flags; ! 168: u16 plcp_len = 0; ! 169: int len = iob_len(iob); ! 170: ! 171: tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | ! 172: RTL818X_TX_DESC_FLAG_LS | (priv->hw_rate << 24) | len; ! 173: ! 174: if (priv->r8185) { ! 175: tx_flags |= RTL818X_TX_DESC_FLAG_DMA | ! 176: RTL818X_TX_DESC_FLAG_NO_ENC; ! 177: } else { ! 178: unsigned int remainder; ! 179: ! 180: plcp_len = DIV_ROUND_UP(16 * (len + 4), ! 181: (dev->rates[dev->rate] * 2) / 10); ! 182: remainder = (16 * (len + 4)) % ! 183: ((dev->rates[dev->rate] * 2) / 10); ! 184: ! 185: if (remainder > 0 && remainder <= 6) ! 186: plcp_len |= 1 << 15; ! 187: } ! 188: ! 189: entry = &priv->tx_ring[priv->tx_prod]; ! 190: ! 191: if (dev->phy_flags & NET80211_PHY_USE_PROTECTION) { ! 192: tx_flags |= RTL818X_TX_DESC_FLAG_CTS; ! 193: tx_flags |= priv->hw_rtscts_rate << 19; ! 194: entry->rts_duration = net80211_cts_duration(dev, len); ! 195: } else { ! 196: entry->rts_duration = 0; ! 197: } ! 198: ! 199: if (entry->flags & RTL818X_TX_DESC_FLAG_OWN) { ! 200: /* card hasn't processed the old packet yet! */ ! 201: return -EBUSY; ! 202: } ! 203: ! 204: priv->tx_buf[priv->tx_prod] = iob; ! 205: priv->tx_prod = (priv->tx_prod + 1) % RTL818X_TX_RING_SIZE; ! 206: ! 207: entry->plcp_len = cpu_to_le16(plcp_len); ! 208: entry->tx_buf = cpu_to_le32(virt_to_bus(iob->data)); ! 209: entry->frame_len = cpu_to_le32(len); ! 210: entry->flags2 = /* alternate retry rate in 100kbps << 4 */ 0; ! 211: entry->retry_limit = RTL818X_MAX_RETRIES; ! 212: entry->flags = cpu_to_le32(tx_flags); ! 213: ! 214: rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << 5)); ! 215: ! 216: return 0; ! 217: } ! 218: ! 219: void rtl818x_set_anaparam(struct rtl818x_priv *priv, u32 anaparam) ! 220: { ! 221: u8 reg; ! 222: ! 223: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); ! 224: reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); ! 225: rtl818x_iowrite8(priv, &priv->map->CONFIG3, ! 226: reg | RTL818X_CONFIG3_ANAPARAM_WRITE); ! 227: rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); ! 228: rtl818x_iowrite8(priv, &priv->map->CONFIG3, ! 229: reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); ! 230: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 231: } ! 232: ! 233: static int rtl818x_init_hw(struct net80211_device *dev) ! 234: { ! 235: struct rtl818x_priv *priv = dev->priv; ! 236: u16 reg; ! 237: ! 238: rtl818x_iowrite8(priv, &priv->map->CMD, 0); ! 239: rtl818x_ioread8(priv, &priv->map->CMD); ! 240: mdelay(10); ! 241: ! 242: /* reset */ ! 243: rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); ! 244: rtl818x_ioread8(priv, &priv->map->CMD); ! 245: ! 246: reg = rtl818x_ioread8(priv, &priv->map->CMD); ! 247: reg &= (1 << 1); ! 248: reg |= RTL818X_CMD_RESET; ! 249: rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET); ! 250: rtl818x_ioread8(priv, &priv->map->CMD); ! 251: mdelay(200); ! 252: ! 253: /* check success of reset */ ! 254: if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) { ! 255: DBG("rtl818x %s: reset timeout!\n", dev->netdev->name); ! 256: return -ETIMEDOUT; ! 257: } ! 258: ! 259: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); ! 260: rtl818x_ioread8(priv, &priv->map->CMD); ! 261: mdelay(200); ! 262: ! 263: if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) { ! 264: /* For cardbus */ ! 265: reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); ! 266: reg |= 1 << 1; ! 267: rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); ! 268: reg = rtl818x_ioread16(priv, &priv->map->FEMR); ! 269: reg |= (1 << 15) | (1 << 14) | (1 << 4); ! 270: rtl818x_iowrite16(priv, &priv->map->FEMR, reg); ! 271: } ! 272: ! 273: rtl818x_iowrite8(priv, &priv->map->MSR, 0); ! 274: ! 275: if (!priv->r8185) ! 276: rtl818x_set_anaparam(priv, priv->anaparam); ! 277: ! 278: rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); ! 279: rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma); ! 280: ! 281: /* TODO: necessary? specs indicate not */ ! 282: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); ! 283: reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); ! 284: rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); ! 285: if (priv->r8185) { ! 286: reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); ! 287: rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); ! 288: } ! 289: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 290: ! 291: /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */ ! 292: ! 293: /* TODO: turn off hw wep on rtl8180 */ ! 294: ! 295: rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); ! 296: ! 297: if (priv->r8185) { ! 298: rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); ! 299: rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); ! 300: rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); ! 301: ! 302: rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); ! 303: ! 304: /* TODO: set ClkRun enable? necessary? */ ! 305: reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); ! 306: rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6)); ! 307: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); ! 308: reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); ! 309: rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); ! 310: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 311: } else { ! 312: rtl818x_iowrite16(priv, &priv->map->BRSR, 0x1); ! 313: rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); ! 314: ! 315: rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); ! 316: rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); ! 317: } ! 318: ! 319: priv->rf->init(dev); ! 320: if (priv->r8185) ! 321: rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); ! 322: return 0; ! 323: } ! 324: ! 325: static int rtl818x_init_rx_ring(struct net80211_device *dev) ! 326: { ! 327: struct rtl818x_priv *priv = dev->priv; ! 328: struct rtl818x_rx_desc *entry; ! 329: int i; ! 330: ! 331: priv->rx_ring = malloc_dma(sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE, ! 332: RTL818X_RING_ALIGN); ! 333: priv->rx_ring_dma = virt_to_bus(priv->rx_ring); ! 334: if (!priv->rx_ring) { ! 335: DBG("rtl818x %s: cannot allocate RX ring\n", dev->netdev->name); ! 336: return -ENOMEM; ! 337: } ! 338: ! 339: memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE); ! 340: priv->rx_idx = 0; ! 341: ! 342: for (i = 0; i < RTL818X_RX_RING_SIZE; i++) { ! 343: struct io_buffer *iob = alloc_iob(MAX_RX_SIZE); ! 344: entry = &priv->rx_ring[i]; ! 345: if (!iob) ! 346: return -ENOMEM; ! 347: ! 348: priv->rx_buf[i] = iob; ! 349: entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data)); ! 350: entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | ! 351: MAX_RX_SIZE); ! 352: } ! 353: entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); ! 354: return 0; ! 355: } ! 356: ! 357: static void rtl818x_free_rx_ring(struct net80211_device *dev) ! 358: { ! 359: struct rtl818x_priv *priv = dev->priv; ! 360: int i; ! 361: ! 362: for (i = 0; i < RTL818X_RX_RING_SIZE; i++) { ! 363: free_iob(priv->rx_buf[i]); ! 364: priv->rx_buf[i] = NULL; ! 365: } ! 366: ! 367: free_dma(priv->rx_ring, sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE); ! 368: priv->rx_ring = NULL; ! 369: } ! 370: ! 371: static int rtl818x_init_tx_ring(struct net80211_device *dev) ! 372: { ! 373: struct rtl818x_priv *priv = dev->priv; ! 374: int i; ! 375: ! 376: priv->tx_ring = malloc_dma(sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE, ! 377: RTL818X_RING_ALIGN); ! 378: priv->tx_ring_dma = virt_to_bus(priv->tx_ring); ! 379: if (!priv->tx_ring) { ! 380: DBG("rtl818x %s: cannot allocate TX ring\n", dev->netdev->name); ! 381: return -ENOMEM; ! 382: } ! 383: ! 384: memset(priv->tx_ring, 0, sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE); ! 385: priv->tx_prod = priv->tx_cons = 0; ! 386: ! 387: for (i = 0; i < RTL818X_TX_RING_SIZE; i++) ! 388: priv->tx_ring[i].next_tx_desc = cpu_to_le32(priv->tx_ring_dma + ! 389: ((i + 1) % RTL818X_TX_RING_SIZE) * sizeof(*priv->tx_ring)); ! 390: ! 391: return 0; ! 392: } ! 393: ! 394: static void rtl818x_free_tx_ring(struct net80211_device *dev) ! 395: { ! 396: struct rtl818x_priv *priv = dev->priv; ! 397: int i; ! 398: ! 399: for (i = 0; i < RTL818X_TX_RING_SIZE; i++) { ! 400: if (priv->tx_buf[i]) ! 401: net80211_tx_complete(dev, priv->tx_buf[i], 0, ECANCELED); ! 402: priv->tx_buf[i] = NULL; ! 403: } ! 404: ! 405: free_dma(priv->tx_ring, sizeof(*priv->tx_ring) * RTL818X_TX_RING_SIZE); ! 406: priv->tx_ring = NULL; ! 407: } ! 408: ! 409: static void rtl818x_irq(struct net80211_device *dev, int enable) ! 410: { ! 411: struct rtl818x_priv *priv = dev->priv; ! 412: rtl818x_iowrite16(priv, &priv->map->INT_MASK, enable? 0xFFFF : 0); ! 413: } ! 414: ! 415: /* Sets the MAC address of the card. */ ! 416: static void rtl818x_set_hwaddr(struct net80211_device *dev, u8 *hwaddr) ! 417: { ! 418: struct rtl818x_priv *priv = dev->priv; ! 419: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); ! 420: rtl818x_iowrite32(priv, (u32 *)&priv->map->MAC[0], ! 421: le32_to_cpu(*(u32 *)hwaddr)); ! 422: rtl818x_iowrite16(priv, (u16 *)&priv->map->MAC[4], ! 423: le16_to_cpu(*(u16 *)(hwaddr + 4))); ! 424: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 425: } ! 426: ! 427: static int rtl818x_start(struct net80211_device *dev) ! 428: { ! 429: struct rtl818x_priv *priv = dev->priv; ! 430: int ret; ! 431: u32 reg; ! 432: ! 433: ret = rtl818x_init_rx_ring(dev); ! 434: if (ret) ! 435: return ret; ! 436: ! 437: ret = rtl818x_init_tx_ring(dev); ! 438: if (ret) ! 439: goto err_free_rings; ! 440: ! 441: ret = rtl818x_init_hw(dev); ! 442: if (ret) ! 443: goto err_free_rings; ! 444: ! 445: rtl818x_set_hwaddr(dev, dev->netdev->ll_addr); ! 446: ! 447: rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); ! 448: rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma); ! 449: ! 450: rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); ! 451: ! 452: rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); ! 453: rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); ! 454: ! 455: reg = RTL818X_RX_CONF_ONLYERLPKT | ! 456: RTL818X_RX_CONF_RX_AUTORESETPHY | ! 457: RTL818X_RX_CONF_MGMT | ! 458: RTL818X_RX_CONF_DATA | ! 459: (7 << 8 /* MAX RX DMA */) | ! 460: RTL818X_RX_CONF_BROADCAST | ! 461: RTL818X_RX_CONF_NICMAC; ! 462: ! 463: if (priv->r8185) ! 464: reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; ! 465: else { ! 466: reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) ! 467: ? RTL818X_RX_CONF_CSDM1 : 0; ! 468: reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2) ! 469: ? RTL818X_RX_CONF_CSDM2 : 0; ! 470: } ! 471: ! 472: priv->rx_conf = reg; ! 473: rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); ! 474: ! 475: if (priv->r8185) { ! 476: reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); ! 477: reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT; ! 478: reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; ! 479: rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); ! 480: ! 481: reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); ! 482: reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; ! 483: reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; ! 484: reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT; ! 485: rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); ! 486: ! 487: /* disable early TX */ ! 488: rtl818x_iowrite8(priv, (u8 *)priv->map + 0xec, 0x3f); ! 489: } ! 490: ! 491: reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); ! 492: reg |= (6 << 21 /* MAX TX DMA */) | ! 493: RTL818X_TX_CONF_NO_ICV; ! 494: ! 495: if (priv->r8185) ! 496: reg &= ~RTL818X_TX_CONF_PROBE_DTS; ! 497: else ! 498: reg &= ~RTL818X_TX_CONF_HW_SEQNUM; ! 499: ! 500: /* different meaning, same value on both rtl8185 and rtl8180 */ ! 501: reg &= ~RTL818X_TX_CONF_SAT_HWPLCP; ! 502: ! 503: rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); ! 504: ! 505: reg = rtl818x_ioread8(priv, &priv->map->CMD); ! 506: reg |= RTL818X_CMD_RX_ENABLE; ! 507: reg |= RTL818X_CMD_TX_ENABLE; ! 508: rtl818x_iowrite8(priv, &priv->map->CMD, reg); ! 509: ! 510: DBG("%s rtl818x: started\n", dev->netdev->name); ! 511: ! 512: return 0; ! 513: ! 514: err_free_rings: ! 515: rtl818x_free_rx_ring(dev); ! 516: if (priv->tx_ring) ! 517: rtl818x_free_tx_ring(dev); ! 518: ! 519: DBG("%s rtl818x: failed to start\n", dev->netdev->name); ! 520: ! 521: return ret; ! 522: } ! 523: ! 524: static void rtl818x_stop(struct net80211_device *dev) ! 525: { ! 526: struct rtl818x_priv *priv = dev->priv; ! 527: u8 reg; ! 528: ! 529: rtl818x_irq(dev, 0); ! 530: ! 531: reg = rtl818x_ioread8(priv, &priv->map->CMD); ! 532: reg &= ~RTL818X_CMD_TX_ENABLE; ! 533: reg &= ~RTL818X_CMD_RX_ENABLE; ! 534: rtl818x_iowrite8(priv, &priv->map->CMD, reg); ! 535: ! 536: priv->rf->stop(dev); ! 537: ! 538: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); ! 539: reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); ! 540: rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); ! 541: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 542: ! 543: rtl818x_free_rx_ring(dev); ! 544: rtl818x_free_tx_ring(dev); ! 545: } ! 546: ! 547: static int rtl818x_config(struct net80211_device *dev, int changed) ! 548: { ! 549: struct rtl818x_priv *priv = dev->priv; ! 550: int i; ! 551: ! 552: if (changed & NET80211_CFG_CHANNEL) ! 553: priv->rf->set_chan(dev, &dev->channels[dev->channel]); ! 554: ! 555: if (changed & NET80211_CFG_ASSOC) { ! 556: for (i = 0; i < ETH_ALEN; i++) ! 557: rtl818x_iowrite8(priv, &priv->map->BSSID[i], dev->bssid[i]); ! 558: rtl818x_iowrite8(priv, &priv->map->MSR, ! 559: dev->state & NET80211_ASSOCIATED? ! 560: RTL818X_MSR_INFRA : RTL818X_MSR_NO_LINK); ! 561: } ! 562: ! 563: if (changed & NET80211_CFG_PHY_PARAMS) ! 564: priv->rf->conf_erp(dev); ! 565: ! 566: if (changed & NET80211_CFG_RATE) { ! 567: /* figure out the hardware rate number for the new ! 568: logical rate */ ! 569: int hw_rate; ! 570: for (hw_rate = 0; hw_rate < RTL818X_NR_RATES && ! 571: rtl818x_rates[hw_rate] != dev->rates[dev->rate]; ! 572: hw_rate++) ! 573: ; ! 574: if (hw_rate >= RTL818X_NR_RATES) ! 575: return -EINVAL; ! 576: ! 577: priv->hw_rate = hw_rate; ! 578: ! 579: /* and the RTS/CTS rate */ ! 580: for (hw_rate = 0; hw_rate < RTL818X_NR_RATES && ! 581: rtl818x_rates[hw_rate] != ! 582: dev->rates[dev->rtscts_rate]; ! 583: hw_rate++) ! 584: ; ! 585: if (hw_rate >= RTL818X_NR_RATES) ! 586: hw_rate = priv->hw_rate; ! 587: ! 588: priv->hw_rtscts_rate = hw_rate; ! 589: } ! 590: ! 591: return 0; ! 592: } ! 593: ! 594: static const u8 rtl818x_eeprom_bits[] = { ! 595: [SPI_BIT_SCLK] = RTL818X_EEPROM_CMD_CK, ! 596: [SPI_BIT_MISO] = RTL818X_EEPROM_CMD_READ, ! 597: [SPI_BIT_MOSI] = RTL818X_EEPROM_CMD_WRITE, ! 598: [SPI_BIT_SS(0)] = RTL818X_EEPROM_CMD_CS, ! 599: }; ! 600: ! 601: static int rtl818x_spi_read_bit(struct bit_basher *basher, unsigned int bit_id) ! 602: { ! 603: struct rtl818x_priv *priv = container_of(basher, struct rtl818x_priv, ! 604: spibit.basher); ! 605: ! 606: u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); ! 607: return reg & rtl818x_eeprom_bits[bit_id]; ! 608: } ! 609: ! 610: static void rtl818x_spi_write_bit(struct bit_basher *basher, ! 611: unsigned int bit_id, unsigned long data) ! 612: { ! 613: struct rtl818x_priv *priv = container_of(basher, struct rtl818x_priv, ! 614: spibit.basher); ! 615: ! 616: u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); ! 617: u8 mask = rtl818x_eeprom_bits[bit_id]; ! 618: reg = (reg & ~mask) | (data & mask); ! 619: ! 620: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); ! 621: ! 622: rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); ! 623: udelay(10); ! 624: } ! 625: ! 626: static struct bit_basher_operations rtl818x_basher_ops = { ! 627: .read = rtl818x_spi_read_bit, ! 628: .write = rtl818x_spi_write_bit, ! 629: }; ! 630: ! 631: #if DBGLVL_MAX ! 632: static const char *rtl818x_rf_names[] = { ! 633: NULL, /* no 0 */ ! 634: "Intersil", "RFMD", /* unsupported 1-2 */ ! 635: "SA2400", "max2820", "GRF5101", /* supported 3-5 */ ! 636: NULL, NULL, NULL, /* no 6-8 */ ! 637: "RTL8225", /* supported 9 */ ! 638: "RTL8255", /* unsupported 10 */ ! 639: }; ! 640: #define RTL818X_NR_RF_NAMES 11 ! 641: #endif ! 642: ! 643: struct net80211_device_operations rtl818x_operations = { ! 644: .open = rtl818x_start, ! 645: .close = rtl818x_stop, ! 646: .transmit = rtl818x_tx, ! 647: .poll = rtl818x_poll, ! 648: .irq = rtl818x_irq, ! 649: .config = rtl818x_config, ! 650: }; ! 651: ! 652: static int rtl818x_probe(struct pci_device *pdev ) ! 653: { ! 654: struct net80211_device *dev; ! 655: struct rtl818x_priv *priv; ! 656: struct rtl818x_rf_ops *rf; ! 657: int err, i; ! 658: const char *chip_name; ! 659: u32 reg; ! 660: u16 eeprom_val; ! 661: struct net80211_hw_info *hwinfo; ! 662: ! 663: hwinfo = zalloc(sizeof(*hwinfo)); ! 664: if (!hwinfo) { ! 665: DBG("rtl818x: hwinfo alloc failed\n"); ! 666: return -ENOMEM; ! 667: } ! 668: ! 669: adjust_pci_device(pdev); ! 670: ! 671: dev = net80211_alloc(sizeof(*priv)); ! 672: if (!dev) { ! 673: DBG("rtl818x: net80211 alloc failed\n"); ! 674: return -ENOMEM; ! 675: } ! 676: ! 677: priv = dev->priv; ! 678: priv->pdev = pdev; ! 679: dev->netdev->dev = &pdev->dev; ! 680: ! 681: priv->map = (struct rtl818x_csr *)pdev->ioaddr; ! 682: if (!priv->map) { ! 683: DBG("rtl818x: cannot find device memory\n"); ! 684: err = -ENXIO; ! 685: goto err_free_dev; ! 686: } ! 687: ! 688: reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); ! 689: reg &= RTL818X_TX_CONF_HWVER_MASK; ! 690: switch (reg) { ! 691: case RTL818X_TX_CONF_R8180_ABCD: ! 692: chip_name = "0"; ! 693: break; ! 694: case RTL818X_TX_CONF_R8180_F: ! 695: chip_name = "0vF"; ! 696: break; ! 697: case RTL818X_TX_CONF_R8185_ABC: ! 698: chip_name = "5"; ! 699: break; ! 700: case RTL818X_TX_CONF_R8185_D: ! 701: chip_name = "5vD"; ! 702: break; ! 703: default: ! 704: DBG("rtl818x: Unknown chip! (0x%x)\n", reg >> 25); ! 705: err = -ENOSYS; ! 706: goto err_free_dev; ! 707: } ! 708: ! 709: priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; ! 710: ! 711: hwinfo->bands = NET80211_BAND_BIT_2GHZ; ! 712: hwinfo->flags = NET80211_HW_RX_HAS_FCS; ! 713: hwinfo->signal_type = NET80211_SIGNAL_ARBITRARY; ! 714: hwinfo->signal_max = 65; ! 715: hwinfo->channel_change_time = 1000; ! 716: ! 717: memcpy(hwinfo->rates[NET80211_BAND_2GHZ], rtl818x_rates, ! 718: sizeof(*rtl818x_rates) * RTL818X_NR_RATES); ! 719: ! 720: if (priv->r8185) { ! 721: hwinfo->modes = NET80211_MODE_B | NET80211_MODE_G; ! 722: hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_RATES; ! 723: } else { ! 724: hwinfo->modes = NET80211_MODE_B; ! 725: hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_B_RATES; ! 726: } ! 727: ! 728: priv->spibit.basher.op = &rtl818x_basher_ops; ! 729: priv->spibit.bus.mode = SPI_MODE_THREEWIRE; ! 730: init_spi_bit_basher(&priv->spibit); ! 731: ! 732: DBG2("rtl818x RX_CONF: %08x\n", rtl818x_ioread32(priv, &priv->map->RX_CONF)); ! 733: ! 734: if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) ! 735: init_at93c66(&priv->eeprom, 16); ! 736: else ! 737: init_at93c46(&priv->eeprom, 16); ! 738: priv->eeprom.bus = &priv->spibit.bus; ! 739: ! 740: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM); ! 741: rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); ! 742: udelay(10); ! 743: ! 744: nvs_read(&priv->eeprom.nvs, 0x06, &eeprom_val, 2); ! 745: DBG2("rtl818x eeprom val = %04x\n", eeprom_val); ! 746: eeprom_val &= 0xFF; ! 747: ! 748: priv->rf = NULL; ! 749: for_each_table_entry(rf, RTL818X_RF_DRIVERS) { ! 750: if (rf->id == eeprom_val) { ! 751: priv->rf = rf; ! 752: break; ! 753: } ! 754: } ! 755: ! 756: if (!priv->rf) { ! 757: #if DBGLVL_MAX ! 758: if (eeprom_val < RTL818X_NR_RF_NAMES && ! 759: rtl818x_rf_names[eeprom_val] != NULL) ! 760: DBG("rtl818x: %s RF frontend not supported!\n", ! 761: rtl818x_rf_names[eeprom_val]); ! 762: else ! 763: DBG("rtl818x: RF frontend #%d not recognized!\n", ! 764: eeprom_val); ! 765: #endif ! 766: ! 767: err = -ENOSYS; ! 768: goto err_free_dev; ! 769: } ! 770: ! 771: nvs_read(&priv->eeprom.nvs, 0x17, &eeprom_val, 2); ! 772: priv->csthreshold = eeprom_val >> 8; ! 773: if (!priv->r8185) { ! 774: nvs_read(&priv->eeprom.nvs, 0xD, &priv->anaparam, 4); ! 775: nvs_read(&priv->eeprom.nvs, 0x19, &priv->rfparam, 2); ! 776: priv->anaparam = le32_to_cpu(priv->anaparam); ! 777: priv->rfparam = le16_to_cpu(priv->rfparam); ! 778: } ! 779: ! 780: /* read the MAC address */ ! 781: nvs_read(&priv->eeprom.nvs, 0x7, hwinfo->hwaddr, 6); ! 782: ! 783: /* CCK TX power */ ! 784: for (i = 0; i < 14; i += 2) { ! 785: u16 txpwr; ! 786: nvs_read(&priv->eeprom.nvs, 0x10 + (i >> 1), &txpwr, 2); ! 787: priv->txpower[i] = txpwr & 0xFF; ! 788: priv->txpower[i + 1] = txpwr >> 8; ! 789: } ! 790: ! 791: /* OFDM TX power */ ! 792: if (priv->r8185) { ! 793: for (i = 0; i < 14; i += 2) { ! 794: u16 txpwr; ! 795: nvs_read(&priv->eeprom.nvs, 0x20 + (i >> 1), &txpwr, 2); ! 796: priv->txpower[i] |= (txpwr & 0xFF) << 8; ! 797: priv->txpower[i + 1] |= txpwr & 0xFF00; ! 798: } ! 799: } ! 800: ! 801: rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); ! 802: ! 803: err = net80211_register(dev, &rtl818x_operations, hwinfo); ! 804: if (err) { ! 805: DBG("rtl818x: cannot register device\n"); ! 806: goto err_free_dev; ! 807: } ! 808: ! 809: free(hwinfo); ! 810: ! 811: DBG("rtl818x: Realtek RTL818%s (RF chip %s) with address %s\n", ! 812: chip_name, priv->rf->name, netdev_addr(dev->netdev)); ! 813: ! 814: return 0; ! 815: ! 816: err_free_dev: ! 817: pci_set_drvdata(pdev, NULL); ! 818: net80211_free(dev); ! 819: free(hwinfo); ! 820: return err; ! 821: } ! 822: ! 823: static void rtl818x_remove(struct pci_device *pdev) ! 824: { ! 825: struct net80211_device *dev = pci_get_drvdata(pdev); ! 826: ! 827: if (!dev) ! 828: return; ! 829: ! 830: net80211_unregister(dev); ! 831: net80211_free(dev); ! 832: } ! 833: ! 834: /* Hide PCI_ROM definitions in here from parserom.pl; the definitions ! 835: that should be used are in rtl8180.c and rtl8185.c. */ ! 836: #define RTL_ROM PCI_ROM ! 837: ! 838: static struct pci_device_id rtl818x_nics[] = { ! 839: RTL_ROM(0x10ec, 0x8185, "rtl8185", "Realtek 8185", 0), ! 840: RTL_ROM(0x1799, 0x700f, "f5d7000", "Belkin F5D7000", 0), ! 841: RTL_ROM(0x1799, 0x701f, "f5d7010", "Belkin F5D7010", 0), ! 842: ! 843: RTL_ROM(0x10ec, 0x8180, "rtl8180", "Realtek 8180", 0), ! 844: RTL_ROM(0x1799, 0x6001, "f5d6001", "Belkin F5D6001", 0), ! 845: RTL_ROM(0x1799, 0x6020, "f5d6020", "Belkin F5D6020", 0), ! 846: RTL_ROM(0x1186, 0x3300, "dwl510", "D-Link DWL-510", 0), ! 847: }; ! 848: ! 849: struct pci_driver rtl818x_driver __pci_driver = { ! 850: .ids = rtl818x_nics, ! 851: .id_count = sizeof(rtl818x_nics) / sizeof(rtl818x_nics[0]), ! 852: .probe = rtl818x_probe, ! 853: .remove = rtl818x_remove, ! 854: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.