/* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2008 by Ben Taylor * Copyright (c) 2007 by Lukas Turek * Copyright (c) 2007 by Jiri Svoboda * Copyright (c) 2007 by Martin Krulis * Copyright (c) 2006 by Damien Bergamini * Copyright (c) 2006 by Florian Stoehr * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #ifndef _ZYD_H #define _ZYD_H #ifdef __cplusplus extern "C" { #endif #include #include #define USBDRV_MAJOR_VER 2 #define USBDRV_MINOR_VER 0 #include #include #define ZYD_DRV_NAME "zyd" #define ZYD_DRV_DESC "Zydas ZD1211(B)" #define ZYD_DRV_REV "V1.1" /* Return the number of fields of an array */ #define ZYD_ARRAY_LENGTH(arr) (sizeof (arr) / sizeof ((arr)[0])) /* * Result type: all functions beginning with zyd_ * should use this to indicate success or failure. * (except for public funcions, of course) * * Detecting error: always use (value != ZYD_SUCCESS) * Indicating error: return ZYD_FAILURE */ typedef enum { ZYD_SUCCESS, ZYD_FAILURE } zyd_res; /* * Chip revision ID */ typedef enum { ZYD_UNKNOWN, ZYD_ZD1211, ZYD_ZD1211B } zyd_mac_rev_t; /* * USB-safe mutual exclusion object. */ typedef struct { boolean_t initialized; /* B_TRUE if properly initialized */ boolean_t held; /* B_TRUE if the object is held */ kmutex_t lock; /* serialize access */ kcondvar_t wait; /* for waiting on release */ } zyd_serial_t; /* * Holds an ioread request status. */ struct zyd_ioread { volatile boolean_t pending; /* ioread is in progress */ volatile boolean_t done; /* response has been received */ volatile boolean_t exc; /* an exception has occured */ void *buffer; /* response buffer */ int buf_len; /* buffer size (bytes) */ }; /* * USB state. */ struct zyd_usb { /* Copy of sc->dip */ dev_info_t *dip; /* Device configuration information */ usb_client_dev_data_t *cdata; boolean_t connected; /* Communication pipe handles */ usb_pipe_handle_t pipe_data_in; usb_pipe_handle_t pipe_data_out; usb_pipe_handle_t pipe_cmd_in; usb_pipe_handle_t pipe_cmd_out; /* Communication endpoint data (copied from descriptor tree) */ usb_ep_data_t ep_data_in; usb_ep_data_t ep_data_out; usb_ep_data_t ep_cmd_in; usb_ep_data_t ep_cmd_out; /* Current ioread request (if any) */ struct zyd_ioread io_read; }; struct zyd_softc; /* forward declaration */ struct zyd_rf { /* RF methods */ zyd_res (*init)(struct zyd_rf *); zyd_res (*switch_radio)(struct zyd_rf *, boolean_t); zyd_res (*set_channel)(struct zyd_rf *, uint8_t); /* RF attributes */ struct zyd_softc *rf_sc; /* back-pointer */ int width; }; /* * per-instance soft-state structure */ struct zyd_softc { /* Serialize access to the soft_state/device */ zyd_serial_t serial; struct zyd_rf sc_rf; dev_info_t *dip; /* timeout for scanning */ timeout_id_t timeout_id; /* USB-specific data */ struct zyd_usb usb; /* Chip revision ZYD1211/ZYD1211B */ zyd_mac_rev_t mac_rev; /* MAC address */ uint8_t macaddr[IEEE80211_ADDR_LEN]; /* net80211 data */ struct ieee80211com ic; boolean_t running; boolean_t suspended; boolean_t resched; uint8_t tx_queued; /* Data from EEPROM */ uint16_t fwbase; uint8_t regdomain; uint16_t fw_rev; uint8_t rf_rev; uint8_t pa_rev; uint8_t fix_cr47; uint8_t fix_cr157; uint8_t pwr_cal[14]; uint8_t pwr_int[14]; uint8_t ofdm36_cal[14]; uint8_t ofdm48_cal[14]; uint8_t ofdm54_cal[14]; /* kstats */ uint32_t tx_nobuf; uint32_t rx_nobuf; uint32_t tx_err; uint32_t rx_err; /* net80211 original state change handler */ int (*newstate)(ieee80211com_t *, enum ieee80211_state, int); }; /* RF-config request */ struct zyd_rfwrite { uint16_t code; uint16_t width; uint16_t bit[32]; }; /* 16-bit I/O register write request */ struct zyd_iowrite16 { uint16_t reg; uint16_t value; }; #pragma pack(1) /* Generic usb command to the ZD chip */ struct zyd_cmd { uint16_t cmd_code; uint8_t data[64]; }; /* ZD prepends this header to an incoming frame. */ struct zyd_plcphdr { uint8_t signal; uint8_t reserved[2]; uint16_t service; /* unaligned! */ }; /* ZD appends this footer to an incoming frame. */ struct zyd_rx_stat { uint8_t rssi; uint8_t signal_cck; uint8_t signal_ofdm; uint8_t cipher; uint8_t flags; }; /* this structure may be unaligned */ struct zyd_rx_desc { #define ZYD_MAX_RXFRAMECNT 3 uint16_t len[ZYD_MAX_RXFRAMECNT]; uint16_t tag; #define ZYD_TAG_MULTIFRAME 0x697e }; /* * Prepended to the 802.11 frame when sending to data_out. */ struct zyd_tx_header { uint8_t rate_mod_flags; uint16_t frame_size; uint8_t type_flags; uint16_t packet_size; uint16_t frame_duration; uint8_t service; uint16_t next_frame_duration; }; #pragma pack() /* * Map USB id to 1211/1211B chip */ typedef struct zyd_usb_info { uint16_t vendor_id; uint16_t product_id; zyd_mac_rev_t mac_rev; } zyd_usb_info_t; /* * Simple lock for callback-waiting. This lock should be used in situations when * one needs to wait for a callback function. It sipmply encapsulates one mutex * and one conditional variable. */ struct zyd_cb_lock { boolean_t done; kmutex_t mutex; kcondvar_t cv; }; /* Bits for rate_mod_flags */ #define ZYD_TX_RMF_RATE(rmf) ((rmf) & 0x0f) #define ZYD_TX_RMF_OFDM 0x10 #define ZYD_TX_RMF_SH_PREAMBLE 0x20 /* CCK */ #define ZYD_TX_RMF_5GHZ 0x40 /* OFDM */ /* Bits for type_flags */ #define ZYD_TX_FLAG_BACKOFF 0x01 #define ZYD_TX_FLAG_MULTICAST 0x02 #define ZYD_TX_FLAG_TYPE(t) (((t) & 0x3) << 2) #define ZYD_TX_TYPE_DATA 0 #define ZYD_TX_TYPE_PS_POLL 1 #define ZYD_TX_TYPE_MGMT 2 #define ZYD_TX_TYPE_CTL 3 #define ZYD_TX_FLAG_WAKEUP 0x10 #define ZYD_TX_FLAG_RTS 0x20 #define ZYD_TX_FLAG_ENCRYPT 0x40 #define ZYD_TX_FLAG_CTS_TO_SELF 0x80 #define ZYD_TX_SERVICE_LENGTH_EXTENSION 0x80 #define ZYD_TX_LIST_COUNT 0x8 #define ZYD_RX_LIST_COUNT 0x8 #define ZYD_USB_REQ_COUNT 0x8 /* * Time in miliseconds to stay on one channel during scan. */ #define ZYD_DWELL_TIME 200000 #define ZYD_SER_SIG B_TRUE #define ZYD_NO_SIG B_FALSE /* Location in the endpoint descriptor tree used by the device */ #define ZYD_USB_CONFIG_NUMBER 1 #define ZYD_USB_IFACE_INDEX 0 #define ZYD_USB_ALT_IF_INDEX 0 #define ZYD_DBG_HW (1<<0) #define ZYD_DBG_FW (1<<1) #define ZYD_DBG_USB (1<<2) #define ZYD_DBG_TX (1<<3) #define ZYD_DBG_RX (1<<4) #define ZYD_DBG_SCAN (1<<5) #define ZYD_DBG_GLD (1<<6) #define ZYD_DBG_80211 (1<<7) #define ZYD_DBG_RESUME (1<<8) #define ZYD_RX_BUF_SIZE (sizeof (struct zyd_rx_desc) + \ ((IEEE80211_MAX_LEN + 3) & ~3) * ZYD_MAX_RXFRAMECNT) /* quickly determine if a given rate is CCK or OFDM */ #define ZYD_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) /* * Calculate the byte offset of a struct member */ #define ZYD_IC_TO_SOFTC(ic)\ (\ (struct zyd_softc *)(\ (uintptr_t)(ic) - offsetof(struct zyd_softc, ic)\ )\ ) /* * The 'struct zyd_usb usb' is stored inside 'struct zyd_softc'. * Using the knowledge of the usb member position, * convert a pointer to 'usb' to a pointer to the zyd_softc. */ #define ZYD_USB_TO_SOFTC(usbp)\ (\ (struct zyd_softc *)(\ (uintptr_t)(usbp) - offsetof(struct zyd_softc, usb)\ )\ ) /* Debugging macros */ #ifdef DEBUG #define ZYD_DEBUG(x) zyd_dbg x #else #define ZYD_DEBUG(x) #endif #define ZYD_WARN zyd_warn extern void *zyd_ssp; #ifdef DEBUG extern uint32_t zyd_dbg_flags; void zyd_dbg(uint32_t dbg_mask, const char *fmt, ...); #endif void zyd_warn(const char *fmt, ...); /* * Functions needed for initializing radios and switching channels */ extern zyd_res zyd_read32(struct zyd_softc *, uint16_t, uint32_t *); extern zyd_res zyd_write32(struct zyd_softc *, uint16_t, uint32_t); extern zyd_res zyd_read16(struct zyd_softc *, uint16_t, uint16_t *); extern zyd_res zyd_write16a(struct zyd_softc *, const struct zyd_iowrite16 *, int); extern zyd_res zyd_write16(struct zyd_softc *, uint16_t, uint16_t); /* * Zydas's own USB-safe synchronization primitive. There are many USB API * functions which forbids that caller holds a mutex. So we're avoiding that * by using out own primitive (it consist of ) */ void zyd_serial_init(struct zyd_softc *sc); zyd_res zyd_serial_enter(struct zyd_softc *sc, boolean_t wait_sig); void zyd_serial_exit(struct zyd_softc *sc); void zyd_serial_deinit(struct zyd_softc *sc); void zyd_cb_lock_init(struct zyd_cb_lock *lock); void zyd_cb_lock_destroy(struct zyd_cb_lock *lock); zyd_res zyd_cb_lock_wait(struct zyd_cb_lock *lock, clock_t timeout); void zyd_cb_lock_signal(struct zyd_cb_lock *lock); /* chipset specific routines */ void zyd_hw_set_channel(struct zyd_softc *sc, uint8_t chan); zyd_res zyd_hw_init(struct zyd_softc *sc); void zyd_hw_deinit(struct zyd_softc *sc); zyd_res zyd_hw_start(struct zyd_softc *sc); void zyd_hw_stop(struct zyd_softc *sc); /* USB specific routines */ zyd_res zyd_usb_init(struct zyd_softc *sc); void zyd_usb_deinit(struct zyd_softc *sc); zyd_res zyd_usb_open_pipes(struct zyd_usb *uc); void zyd_usb_close_pipes(struct zyd_usb *uc); zyd_res zyd_usb_cmd_in_start_polling(struct zyd_usb *uc); void zyd_usb_cmd_in_stop_polling(struct zyd_usb *uc); zyd_res zyd_usb_data_in_enable(struct zyd_usb *uc); void zyd_usb_data_in_disable(struct zyd_usb *uc); zyd_res zyd_usb_cmd_send(struct zyd_usb *uc, uint16_t code, const void *data, size_t len); zyd_res zyd_usb_ioread_req(struct zyd_usb *uc, const void *in_data, size_t in_len, void *out_data, size_t out_len); zyd_res zyd_usb_send_packet(struct zyd_usb *uc, mblk_t *mp); zyd_mac_rev_t zyd_usb_mac_rev(uint16_t vendor, uint16_t product); zyd_res zyd_usb_loadfirmware(struct zyd_usb *uc, uint8_t *fw, size_t size); void zyd_receive(struct zyd_softc *sc, const uint8_t *buf, uint16_t len); int zyd_resume(struct zyd_softc *sc); int zyd_suspend(struct zyd_softc *sc); extern uint8_t zd1211_firmware[]; extern size_t zd1211_firmware_size; extern uint8_t zd1211b_firmware[]; extern size_t zd1211b_firmware_size; #ifdef __cplusplus } #endif #endif /* _ZYD_H */