?? zd_chip.c
字號:
/* zd_chip.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* This file implements all the hardware specific functions for the ZD1211 * and ZD1211B chips. Support for the ZD1211B was possible after Timothy * Legge sent me a ZD1211B device. Thank you Tim. -- Uli */#include <linux/kernel.h>#include <linux/errno.h>#include "zd_def.h"#include "zd_chip.h"#include "zd_ieee80211.h"#include "zd_mac.h"#include "zd_rf.h"#include "zd_util.h"void zd_chip_init(struct zd_chip *chip, struct net_device *netdev, struct usb_interface *intf){ memset(chip, 0, sizeof(*chip)); mutex_init(&chip->mutex); zd_usb_init(&chip->usb, netdev, intf); zd_rf_init(&chip->rf);}void zd_chip_clear(struct zd_chip *chip){ mutex_lock(&chip->mutex); zd_usb_clear(&chip->usb); zd_rf_clear(&chip->rf); mutex_unlock(&chip->mutex); mutex_destroy(&chip->mutex); memset(chip, 0, sizeof(*chip));}static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size){ return scnprintf(buffer, size, "%02x-%02x-%02x", addr[0], addr[1], addr[2]);}/* Prints an identifier line, which will support debugging. */static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size){ int i = 0; i = scnprintf(buffer, size, "zd1211%s chip ", chip->is_zd1211b ? "b" : ""); i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, chip->patch_cck_gain ? 'g' : '-', chip->patch_cr157 ? '7' : '-', chip->patch_6m_band_edge ? '6' : '-'); return i;}static void print_id(struct zd_chip *chip){ char buffer[80]; scnprint_id(chip, buffer, sizeof(buffer)); buffer[sizeof(buffer)-1] = 0; dev_info(zd_chip_dev(chip), "%s\n", buffer);}/* Read a variable number of 32-bit values. Parameter count is not allowed to * exceed USB_MAX_IOREAD32_COUNT. */int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr, unsigned int count){ int r; int i; zd_addr_t *a16 = (zd_addr_t *)NULL; u16 *v16; unsigned int count16; if (count > USB_MAX_IOREAD32_COUNT) return -EINVAL; /* Allocate a single memory block for values and addresses. */ count16 = 2*count; a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), GFP_NOFS); if (!a16) { dev_dbg_f(zd_chip_dev(chip), "error ENOMEM in allocation of a16\n"); r = -ENOMEM; goto out; } v16 = (u16 *)(a16 + count16); for (i = 0; i < count; i++) { int j = 2*i; /* We read the high word always first. */ a16[j] = zd_inc_word(addr[i]); a16[j+1] = addr[i]; } r = zd_ioread16v_locked(chip, v16, a16, count16); if (r) { dev_dbg_f(zd_chip_dev(chip), "error: zd_ioread16v_locked. Error number %d\n", r); goto out; } for (i = 0; i < count; i++) { int j = 2*i; values[i] = (v16[j] << 16) | v16[j+1]; }out: kfree((void *)a16); return r;}int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, unsigned int count){ int i, j, r; struct zd_ioreq16 *ioreqs16; unsigned int count16; ZD_ASSERT(mutex_is_locked(&chip->mutex)); if (count == 0) return 0; if (count > USB_MAX_IOWRITE32_COUNT) return -EINVAL; /* Allocate a single memory block for values and addresses. */ count16 = 2*count; ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS); if (!ioreqs16) { r = -ENOMEM; dev_dbg_f(zd_chip_dev(chip), "error %d in ioreqs16 allocation\n", r); goto out; } for (i = 0; i < count; i++) { j = 2*i; /* We write the high word always first. */ ioreqs16[j].value = ioreqs[i].value >> 16; ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr); ioreqs16[j+1].value = ioreqs[i].value; ioreqs16[j+1].addr = ioreqs[i].addr; } r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16);#ifdef DEBUG if (r) { dev_dbg_f(zd_chip_dev(chip), "error %d in zd_usb_write16v\n", r); }#endif /* DEBUG */out: kfree(ioreqs16); return r;}int zd_iowrite16a_locked(struct zd_chip *chip, const struct zd_ioreq16 *ioreqs, unsigned int count){ int r; unsigned int i, j, t, max; ZD_ASSERT(mutex_is_locked(&chip->mutex)); for (i = 0; i < count; i += j + t) { t = 0; max = count-i; if (max > USB_MAX_IOWRITE16_COUNT) max = USB_MAX_IOWRITE16_COUNT; for (j = 0; j < max; j++) { if (!ioreqs[i+j].addr) { t = 1; break; } } r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); if (r) { dev_dbg_f(zd_chip_dev(chip), "error zd_usb_iowrite16v. Error number %d\n", r); return r; } } return 0;}/* Writes a variable number of 32 bit registers. The functions will split * that in several USB requests. A split can be forced by inserting an IO * request with an zero address field. */int zd_iowrite32a_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, unsigned int count){ int r; unsigned int i, j, t, max; for (i = 0; i < count; i += j + t) { t = 0; max = count-i; if (max > USB_MAX_IOWRITE32_COUNT) max = USB_MAX_IOWRITE32_COUNT; for (j = 0; j < max; j++) { if (!ioreqs[i+j].addr) { t = 1; break; } } r = _zd_iowrite32v_locked(chip, &ioreqs[i], j); if (r) { dev_dbg_f(zd_chip_dev(chip), "error _zd_iowrite32v_locked." " Error number %d\n", r); return r; } } return 0;}int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_ioread16_locked(chip, value, addr); mutex_unlock(&chip->mutex); return r;}int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_ioread32_locked(chip, value, addr); mutex_unlock(&chip->mutex); return r;}int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_iowrite16_locked(chip, value, addr); mutex_unlock(&chip->mutex); return r;}int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_iowrite32_locked(chip, value, addr); mutex_unlock(&chip->mutex); return r;}int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, u32 *values, unsigned int count){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_ioread32v_locked(chip, values, addresses, count); mutex_unlock(&chip->mutex); return r;}int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, unsigned int count){ int r; ZD_ASSERT(!mutex_is_locked(&chip->mutex)); mutex_lock(&chip->mutex); r = zd_iowrite32a_locked(chip, ioreqs, count); mutex_unlock(&chip->mutex); return r;}static int read_pod(struct zd_chip *chip, u8 *rf_type){ int r; u32 value; ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_ioread32_locked(chip, &value, E2P_POD); if (r) goto error; dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); /* FIXME: AL2230 handling (Bit 7 in POD) */ *rf_type = value & 0x0f; chip->pa_type = (value >> 16) & 0x0f; chip->patch_cck_gain = (value >> 8) & 0x1; chip->patch_cr157 = (value >> 13) & 0x1; chip->patch_6m_band_edge = (value >> 21) & 0x1; dev_dbg_f(zd_chip_dev(chip), "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " "patch 6M %d\n", zd_rf_name(*rf_type), *rf_type, chip->pa_type, chip->patch_cck_gain, chip->patch_cr157, chip->patch_6m_band_edge); return 0;error: *rf_type = 0; chip->pa_type = 0; chip->patch_cck_gain = 0; chip->patch_cr157 = 0; chip->patch_6m_band_edge = 0; return r;}static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, const zd_addr_t *addr){ int r; u32 parts[2]; r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); if (r) { dev_dbg_f(zd_chip_dev(chip), "error: couldn't read e2p macs. Error number %d\n", r); return r; } mac_addr[0] = parts[0]; mac_addr[1] = parts[0] >> 8; mac_addr[2] = parts[0] >> 16; mac_addr[3] = parts[0] >> 24; mac_addr[4] = parts[1]; mac_addr[5] = parts[1] >> 8; return 0;}static int read_e2p_mac_addr(struct zd_chip *chip){ static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);}/* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and * CR_MAC_ADDR_P2 must be overwritten */void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr){ mutex_lock(&chip->mutex); memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); mutex_unlock(&chip->mutex);}static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr){ static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);}int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr){ int r; dev_dbg_f(zd_chip_dev(chip), "\n"); mutex_lock(&chip->mutex); r = read_mac_addr(chip, mac_addr); mutex_unlock(&chip->mutex); return r;}int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr){ int r; struct zd_ioreq32 reqs[2] = { [0] = { .addr = CR_MAC_ADDR_P1 }, [1] = { .addr = CR_MAC_ADDR_P2 }, }; reqs[0].value = (mac_addr[3] << 24) | (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]; reqs[1].value = (mac_addr[5] << 8) | mac_addr[4]; dev_dbg_f(zd_chip_dev(chip), "mac addr " MAC_FMT "\n", MAC_ARG(mac_addr)); mutex_lock(&chip->mutex); r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));#ifdef DEBUG { u8 tmp[ETH_ALEN]; read_mac_addr(chip, tmp); }#endif /* DEBUG */ mutex_unlock(&chip->mutex); return r;}int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain){ int r; u32 value; mutex_lock(&chip->mutex); r = zd_ioread32_locked(chip, &value, E2P_SUBID); mutex_unlock(&chip->mutex); if (r) return r; *regdomain = value >> 16; dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain); return 0;}static int read_values(struct zd_chip *chip, u8 *values, size_t count, zd_addr_t e2p_addr, u32 guard){ int r; int i; u32 v; ZD_ASSERT(mutex_is_locked(&chip->mutex)); for (i = 0;;) { r = zd_ioread32_locked(chip, &v, e2p_addr+i/2); if (r) return r; v -= guard; if (i+4 < count) { values[i++] = v; values[i++] = v >> 8; values[i++] = v >> 16; values[i++] = v >> 24; continue; } for (;i < count; i++) values[i] = v >> (8*(i%3)); return 0; }}static int read_pwr_cal_values(struct zd_chip *chip){ return read_values(chip, chip->pwr_cal_values, E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1, 0);}static int read_pwr_int_values(struct zd_chip *chip){ return read_values(chip, chip->pwr_int_values, E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1, E2P_PWR_INT_GUARD);}static int read_ofdm_cal_values(struct zd_chip *chip){ int r; int i; static const zd_addr_t addresses[] = { E2P_36M_CAL_VALUE1, E2P_48M_CAL_VALUE1, E2P_54M_CAL_VALUE1, }; for (i = 0; i < 3; i++) { r = read_values(chip, chip->ofdm_cal_values[i], E2P_CHANNEL_COUNT, addresses[i], 0); if (r) return r; } return 0;}static int read_cal_int_tables(struct zd_chip *chip){ int r; r = read_pwr_cal_values(chip); if (r) return r; r = read_pwr_int_values(chip); if (r) return r; r = read_ofdm_cal_values(chip); if (r) return r; return 0;}/* phy means physical registers */int zd_chip_lock_phy_regs(struct zd_chip *chip){ int r; u32 tmp; ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_ioread32_locked(chip, &tmp, CR_REG1); if (r) { dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r); return r; } dev_dbg_f(zd_chip_dev(chip), "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp & ~UNLOCK_PHY_REGS); tmp &= ~UNLOCK_PHY_REGS; r = zd_iowrite32_locked(chip, tmp, CR_REG1); if (r) dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -