162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* hermes.h 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Driver core for the "Hermes" wireless MAC controller, as used in 562306a36Sopenharmony_ci * the Lucent Orinoco and Cabletron RoamAbout cards. It should also 662306a36Sopenharmony_ci * work on the hfa3841 and hfa3842 MAC controller chips used in the 762306a36Sopenharmony_ci * Prism I & II chipsets. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This is not a complete driver, just low-level access routines for 1062306a36Sopenharmony_ci * the MAC controller itself. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Based on the prism2 driver from Absolute Value Systems' linux-wlan 1362306a36Sopenharmony_ci * project, the Linux wvlan_cs driver, Lucent's HCF-Light 1462306a36Sopenharmony_ci * (wvlan_hcf.c) library, and the NetBSD wireless driver. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Copyright (C) 2000, David Gibson, Linuxcare Australia. 1762306a36Sopenharmony_ci * (C) Copyright David Gibson, IBM Corp. 2001-2003. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Portions taken from hfa384x.h. 2062306a36Sopenharmony_ci * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifndef _HERMES_H 2462306a36Sopenharmony_ci#define _HERMES_H 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* Notes on locking: 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * As a module of low level hardware access routines, there is no 2962306a36Sopenharmony_ci * locking. Users of this module should ensure that they serialize 3062306a36Sopenharmony_ci * access to the hermes structure, and to the hardware 3162306a36Sopenharmony_ci*/ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <linux/if_ether.h> 3462306a36Sopenharmony_ci#include <linux/io.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * Limits and constants 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci#define HERMES_ALLOC_LEN_MIN (4) 4062306a36Sopenharmony_ci#define HERMES_ALLOC_LEN_MAX (2400) 4162306a36Sopenharmony_ci#define HERMES_LTV_LEN_MAX (34) 4262306a36Sopenharmony_ci#define HERMES_BAP_DATALEN_MAX (4096) 4362306a36Sopenharmony_ci#define HERMES_BAP_OFFSET_MAX (4096) 4462306a36Sopenharmony_ci#define HERMES_PORTID_MAX (7) 4562306a36Sopenharmony_ci#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1) 4662306a36Sopenharmony_ci#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */ 4762306a36Sopenharmony_ci#define HERMES_PDA_RECS_MAX (200) /* a guess */ 4862306a36Sopenharmony_ci#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */ 4962306a36Sopenharmony_ci#define HERMES_SCANRESULT_MAX (35) 5062306a36Sopenharmony_ci#define HERMES_CHINFORESULT_MAX (8) 5162306a36Sopenharmony_ci#define HERMES_MAX_MULTICAST (16) 5262306a36Sopenharmony_ci#define HERMES_MAGIC (0x7d1f) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* 5562306a36Sopenharmony_ci * Hermes register offsets 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci#define HERMES_CMD (0x00) 5862306a36Sopenharmony_ci#define HERMES_PARAM0 (0x02) 5962306a36Sopenharmony_ci#define HERMES_PARAM1 (0x04) 6062306a36Sopenharmony_ci#define HERMES_PARAM2 (0x06) 6162306a36Sopenharmony_ci#define HERMES_STATUS (0x08) 6262306a36Sopenharmony_ci#define HERMES_RESP0 (0x0A) 6362306a36Sopenharmony_ci#define HERMES_RESP1 (0x0C) 6462306a36Sopenharmony_ci#define HERMES_RESP2 (0x0E) 6562306a36Sopenharmony_ci#define HERMES_INFOFID (0x10) 6662306a36Sopenharmony_ci#define HERMES_RXFID (0x20) 6762306a36Sopenharmony_ci#define HERMES_ALLOCFID (0x22) 6862306a36Sopenharmony_ci#define HERMES_TXCOMPLFID (0x24) 6962306a36Sopenharmony_ci#define HERMES_SELECT0 (0x18) 7062306a36Sopenharmony_ci#define HERMES_OFFSET0 (0x1C) 7162306a36Sopenharmony_ci#define HERMES_DATA0 (0x36) 7262306a36Sopenharmony_ci#define HERMES_SELECT1 (0x1A) 7362306a36Sopenharmony_ci#define HERMES_OFFSET1 (0x1E) 7462306a36Sopenharmony_ci#define HERMES_DATA1 (0x38) 7562306a36Sopenharmony_ci#define HERMES_EVSTAT (0x30) 7662306a36Sopenharmony_ci#define HERMES_INTEN (0x32) 7762306a36Sopenharmony_ci#define HERMES_EVACK (0x34) 7862306a36Sopenharmony_ci#define HERMES_CONTROL (0x14) 7962306a36Sopenharmony_ci#define HERMES_SWSUPPORT0 (0x28) 8062306a36Sopenharmony_ci#define HERMES_SWSUPPORT1 (0x2A) 8162306a36Sopenharmony_ci#define HERMES_SWSUPPORT2 (0x2C) 8262306a36Sopenharmony_ci#define HERMES_AUXPAGE (0x3A) 8362306a36Sopenharmony_ci#define HERMES_AUXOFFSET (0x3C) 8462306a36Sopenharmony_ci#define HERMES_AUXDATA (0x3E) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * CMD register bitmasks 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci#define HERMES_CMD_BUSY (0x8000) 9062306a36Sopenharmony_ci#define HERMES_CMD_AINFO (0x7f00) 9162306a36Sopenharmony_ci#define HERMES_CMD_MACPORT (0x0700) 9262306a36Sopenharmony_ci#define HERMES_CMD_RECL (0x0100) 9362306a36Sopenharmony_ci#define HERMES_CMD_WRITE (0x0100) 9462306a36Sopenharmony_ci#define HERMES_CMD_PROGMODE (0x0300) 9562306a36Sopenharmony_ci#define HERMES_CMD_CMDCODE (0x003f) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * STATUS register bitmasks 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci#define HERMES_STATUS_RESULT (0x7f00) 10162306a36Sopenharmony_ci#define HERMES_STATUS_CMDCODE (0x003f) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* 10462306a36Sopenharmony_ci * OFFSET register bitmasks 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_ci#define HERMES_OFFSET_BUSY (0x8000) 10762306a36Sopenharmony_ci#define HERMES_OFFSET_ERR (0x4000) 10862306a36Sopenharmony_ci#define HERMES_OFFSET_DATAOFF (0x0ffe) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* 11162306a36Sopenharmony_ci * Event register bitmasks (INTEN, EVSTAT, EVACK) 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ci#define HERMES_EV_TICK (0x8000) 11462306a36Sopenharmony_ci#define HERMES_EV_WTERR (0x4000) 11562306a36Sopenharmony_ci#define HERMES_EV_INFDROP (0x2000) 11662306a36Sopenharmony_ci#define HERMES_EV_INFO (0x0080) 11762306a36Sopenharmony_ci#define HERMES_EV_DTIM (0x0020) 11862306a36Sopenharmony_ci#define HERMES_EV_CMD (0x0010) 11962306a36Sopenharmony_ci#define HERMES_EV_ALLOC (0x0008) 12062306a36Sopenharmony_ci#define HERMES_EV_TXEXC (0x0004) 12162306a36Sopenharmony_ci#define HERMES_EV_TX (0x0002) 12262306a36Sopenharmony_ci#define HERMES_EV_RX (0x0001) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* 12562306a36Sopenharmony_ci * Command codes 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci/*--- Controller Commands ----------------------------*/ 12862306a36Sopenharmony_ci#define HERMES_CMD_INIT (0x0000) 12962306a36Sopenharmony_ci#define HERMES_CMD_ENABLE (0x0001) 13062306a36Sopenharmony_ci#define HERMES_CMD_DISABLE (0x0002) 13162306a36Sopenharmony_ci#define HERMES_CMD_DIAG (0x0003) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/*--- Buffer Mgmt Commands ---------------------------*/ 13462306a36Sopenharmony_ci#define HERMES_CMD_ALLOC (0x000A) 13562306a36Sopenharmony_ci#define HERMES_CMD_TX (0x000B) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/*--- Regulate Commands ------------------------------*/ 13862306a36Sopenharmony_ci#define HERMES_CMD_NOTIFY (0x0010) 13962306a36Sopenharmony_ci#define HERMES_CMD_INQUIRE (0x0011) 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/*--- Configure Commands -----------------------------*/ 14262306a36Sopenharmony_ci#define HERMES_CMD_ACCESS (0x0021) 14362306a36Sopenharmony_ci#define HERMES_CMD_DOWNLD (0x0022) 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/*--- Serial I/O Commands ----------------------------*/ 14662306a36Sopenharmony_ci#define HERMES_CMD_READMIF (0x0030) 14762306a36Sopenharmony_ci#define HERMES_CMD_WRITEMIF (0x0031) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/*--- Debugging Commands -----------------------------*/ 15062306a36Sopenharmony_ci#define HERMES_CMD_TEST (0x0038) 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* Test command arguments */ 15462306a36Sopenharmony_ci#define HERMES_TEST_SET_CHANNEL 0x0800 15562306a36Sopenharmony_ci#define HERMES_TEST_MONITOR 0x0b00 15662306a36Sopenharmony_ci#define HERMES_TEST_STOP 0x0f00 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* Authentication algorithms */ 15962306a36Sopenharmony_ci#define HERMES_AUTH_OPEN 1 16062306a36Sopenharmony_ci#define HERMES_AUTH_SHARED_KEY 2 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* WEP settings */ 16362306a36Sopenharmony_ci#define HERMES_WEP_PRIVACY_INVOKED 0x0001 16462306a36Sopenharmony_ci#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002 16562306a36Sopenharmony_ci#define HERMES_WEP_HOST_ENCRYPT 0x0010 16662306a36Sopenharmony_ci#define HERMES_WEP_HOST_DECRYPT 0x0080 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/* Symbol hostscan options */ 16962306a36Sopenharmony_ci#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001 17062306a36Sopenharmony_ci#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002 17162306a36Sopenharmony_ci#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040 17262306a36Sopenharmony_ci#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * Frame structures and constants 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define HERMES_DESCRIPTOR_OFFSET 0 17962306a36Sopenharmony_ci#define HERMES_802_11_OFFSET (14) 18062306a36Sopenharmony_ci#define HERMES_802_3_OFFSET (14 + 32) 18162306a36Sopenharmony_ci#define HERMES_802_2_OFFSET (14 + 32 + 14) 18262306a36Sopenharmony_ci#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2) 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define HERMES_RXSTAT_ERR (0x0003) 18562306a36Sopenharmony_ci#define HERMES_RXSTAT_BADCRC (0x0001) 18662306a36Sopenharmony_ci#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) 18762306a36Sopenharmony_ci#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */ 18862306a36Sopenharmony_ci#define HERMES_RXSTAT_MACPORT (0x0700) 18962306a36Sopenharmony_ci#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */ 19062306a36Sopenharmony_ci#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */ 19162306a36Sopenharmony_ci#define HERMES_RXSTAT_MSGTYPE (0xE000) 19262306a36Sopenharmony_ci#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */ 19362306a36Sopenharmony_ci#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */ 19462306a36Sopenharmony_ci#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */ 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/* Shift amount for key ID in RXSTAT and TXCTRL */ 19762306a36Sopenharmony_ci#define HERMES_MIC_KEY_ID_SHIFT 11 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistruct hermes_tx_descriptor { 20062306a36Sopenharmony_ci __le16 status; 20162306a36Sopenharmony_ci __le16 reserved1; 20262306a36Sopenharmony_ci __le16 reserved2; 20362306a36Sopenharmony_ci __le32 sw_support; 20462306a36Sopenharmony_ci u8 retry_count; 20562306a36Sopenharmony_ci u8 tx_rate; 20662306a36Sopenharmony_ci __le16 tx_control; 20762306a36Sopenharmony_ci} __packed; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define HERMES_TXSTAT_RETRYERR (0x0001) 21062306a36Sopenharmony_ci#define HERMES_TXSTAT_AGEDERR (0x0002) 21162306a36Sopenharmony_ci#define HERMES_TXSTAT_DISCON (0x0004) 21262306a36Sopenharmony_ci#define HERMES_TXSTAT_FORMERR (0x0008) 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */ 21562306a36Sopenharmony_ci#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */ 21662306a36Sopenharmony_ci#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */ 21762306a36Sopenharmony_ci#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */ 21862306a36Sopenharmony_ci#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */ 21962306a36Sopenharmony_ci#define HERMES_TXCTRL_ALT_RTRY (0x0020) 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/* Inquiry constants and data types */ 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci#define HERMES_INQ_TALLIES (0xF100) 22462306a36Sopenharmony_ci#define HERMES_INQ_SCAN (0xF101) 22562306a36Sopenharmony_ci#define HERMES_INQ_CHANNELINFO (0xF102) 22662306a36Sopenharmony_ci#define HERMES_INQ_HOSTSCAN (0xF103) 22762306a36Sopenharmony_ci#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104) 22862306a36Sopenharmony_ci#define HERMES_INQ_LINKSTATUS (0xF200) 22962306a36Sopenharmony_ci#define HERMES_INQ_SEC_STAT_AGERE (0xF202) 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistruct hermes_tallies_frame { 23262306a36Sopenharmony_ci __le16 TxUnicastFrames; 23362306a36Sopenharmony_ci __le16 TxMulticastFrames; 23462306a36Sopenharmony_ci __le16 TxFragments; 23562306a36Sopenharmony_ci __le16 TxUnicastOctets; 23662306a36Sopenharmony_ci __le16 TxMulticastOctets; 23762306a36Sopenharmony_ci __le16 TxDeferredTransmissions; 23862306a36Sopenharmony_ci __le16 TxSingleRetryFrames; 23962306a36Sopenharmony_ci __le16 TxMultipleRetryFrames; 24062306a36Sopenharmony_ci __le16 TxRetryLimitExceeded; 24162306a36Sopenharmony_ci __le16 TxDiscards; 24262306a36Sopenharmony_ci __le16 RxUnicastFrames; 24362306a36Sopenharmony_ci __le16 RxMulticastFrames; 24462306a36Sopenharmony_ci __le16 RxFragments; 24562306a36Sopenharmony_ci __le16 RxUnicastOctets; 24662306a36Sopenharmony_ci __le16 RxMulticastOctets; 24762306a36Sopenharmony_ci __le16 RxFCSErrors; 24862306a36Sopenharmony_ci __le16 RxDiscards_NoBuffer; 24962306a36Sopenharmony_ci __le16 TxDiscardsWrongSA; 25062306a36Sopenharmony_ci __le16 RxWEPUndecryptable; 25162306a36Sopenharmony_ci __le16 RxMsgInMsgFragments; 25262306a36Sopenharmony_ci __le16 RxMsgInBadMsgFragments; 25362306a36Sopenharmony_ci /* Those last are probably not available in very old firmwares */ 25462306a36Sopenharmony_ci __le16 RxDiscards_WEPICVError; 25562306a36Sopenharmony_ci __le16 RxDiscards_WEPExcluded; 25662306a36Sopenharmony_ci} __packed; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/* Grabbed from wlan-ng - Thanks Mark... - Jean II 25962306a36Sopenharmony_ci * This is the result of a scan inquiry command */ 26062306a36Sopenharmony_ci/* Structure describing info about an Access Point */ 26162306a36Sopenharmony_cistruct prism2_scan_apinfo { 26262306a36Sopenharmony_ci __le16 channel; /* Channel where the AP sits */ 26362306a36Sopenharmony_ci __le16 noise; /* Noise level */ 26462306a36Sopenharmony_ci __le16 level; /* Signal level */ 26562306a36Sopenharmony_ci u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ 26662306a36Sopenharmony_ci __le16 beacon_interv; /* Beacon interval */ 26762306a36Sopenharmony_ci __le16 capabilities; /* Capabilities */ 26862306a36Sopenharmony_ci __le16 essid_len; /* ESSID length */ 26962306a36Sopenharmony_ci u8 essid[32]; /* ESSID of the network */ 27062306a36Sopenharmony_ci u8 rates[10]; /* Bit rate supported */ 27162306a36Sopenharmony_ci __le16 proberesp_rate; /* Data rate of the response frame */ 27262306a36Sopenharmony_ci __le16 atim; /* ATIM window time, Kus (hostscan only) */ 27362306a36Sopenharmony_ci} __packed; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* Same stuff for the Lucent/Agere card. 27662306a36Sopenharmony_ci * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */ 27762306a36Sopenharmony_cistruct agere_scan_apinfo { 27862306a36Sopenharmony_ci __le16 channel; /* Channel where the AP sits */ 27962306a36Sopenharmony_ci __le16 noise; /* Noise level */ 28062306a36Sopenharmony_ci __le16 level; /* Signal level */ 28162306a36Sopenharmony_ci u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ 28262306a36Sopenharmony_ci __le16 beacon_interv; /* Beacon interval */ 28362306a36Sopenharmony_ci __le16 capabilities; /* Capabilities */ 28462306a36Sopenharmony_ci /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ 28562306a36Sopenharmony_ci __le16 essid_len; /* ESSID length */ 28662306a36Sopenharmony_ci u8 essid[32]; /* ESSID of the network */ 28762306a36Sopenharmony_ci} __packed; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/* Moustafa: Scan structure for Symbol cards */ 29062306a36Sopenharmony_cistruct symbol_scan_apinfo { 29162306a36Sopenharmony_ci u8 channel; /* Channel where the AP sits */ 29262306a36Sopenharmony_ci u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */ 29362306a36Sopenharmony_ci __le16 noise; /* Noise level */ 29462306a36Sopenharmony_ci __le16 level; /* Signal level */ 29562306a36Sopenharmony_ci u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ 29662306a36Sopenharmony_ci __le16 beacon_interv; /* Beacon interval */ 29762306a36Sopenharmony_ci __le16 capabilities; /* Capabilities */ 29862306a36Sopenharmony_ci /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ 29962306a36Sopenharmony_ci __le16 essid_len; /* ESSID length */ 30062306a36Sopenharmony_ci u8 essid[32]; /* ESSID of the network */ 30162306a36Sopenharmony_ci __le16 rates[5]; /* Bit rate supported */ 30262306a36Sopenharmony_ci __le16 basic_rates; /* Basic rates bitmask */ 30362306a36Sopenharmony_ci u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */ 30462306a36Sopenharmony_ci u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */ 30562306a36Sopenharmony_ci} __packed; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ciunion hermes_scan_info { 30862306a36Sopenharmony_ci struct agere_scan_apinfo a; 30962306a36Sopenharmony_ci struct prism2_scan_apinfo p; 31062306a36Sopenharmony_ci struct symbol_scan_apinfo s; 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* Extended scan struct for HERMES_INQ_CHANNELINFO. 31462306a36Sopenharmony_ci * wl_lkm calls this an ACS scan (Automatic Channel Select). 31562306a36Sopenharmony_ci * Keep out of union hermes_scan_info because it is much bigger than 31662306a36Sopenharmony_ci * the older scan structures. */ 31762306a36Sopenharmony_cistruct agere_ext_scan_info { 31862306a36Sopenharmony_ci __le16 reserved0; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci u8 noise; 32162306a36Sopenharmony_ci u8 level; 32262306a36Sopenharmony_ci u8 rx_flow; 32362306a36Sopenharmony_ci u8 rate; 32462306a36Sopenharmony_ci __le16 reserved1[2]; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci __le16 frame_control; 32762306a36Sopenharmony_ci __le16 dur_id; 32862306a36Sopenharmony_ci u8 addr1[ETH_ALEN]; 32962306a36Sopenharmony_ci u8 addr2[ETH_ALEN]; 33062306a36Sopenharmony_ci u8 bssid[ETH_ALEN]; 33162306a36Sopenharmony_ci __le16 sequence; 33262306a36Sopenharmony_ci u8 addr4[ETH_ALEN]; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci __le16 data_length; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Next 3 fields do not get filled in. */ 33762306a36Sopenharmony_ci u8 daddr[ETH_ALEN]; 33862306a36Sopenharmony_ci u8 saddr[ETH_ALEN]; 33962306a36Sopenharmony_ci __le16 len_type; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci __le64 timestamp; 34262306a36Sopenharmony_ci __le16 beacon_interval; 34362306a36Sopenharmony_ci __le16 capabilities; 34462306a36Sopenharmony_ci u8 data[]; 34562306a36Sopenharmony_ci} __packed; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) 34862306a36Sopenharmony_ci#define HERMES_LINKSTATUS_CONNECTED (0x0001) 34962306a36Sopenharmony_ci#define HERMES_LINKSTATUS_DISCONNECTED (0x0002) 35062306a36Sopenharmony_ci#define HERMES_LINKSTATUS_AP_CHANGE (0x0003) 35162306a36Sopenharmony_ci#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004) 35262306a36Sopenharmony_ci#define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005) 35362306a36Sopenharmony_ci#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006) 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistruct hermes_linkstatus { 35662306a36Sopenharmony_ci __le16 linkstatus; /* Link status */ 35762306a36Sopenharmony_ci} __packed; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistruct hermes_response { 36062306a36Sopenharmony_ci u16 status, resp0, resp1, resp2; 36162306a36Sopenharmony_ci}; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* "ID" structure - used for ESSID and station nickname */ 36462306a36Sopenharmony_cistruct hermes_idstring { 36562306a36Sopenharmony_ci __le16 len; 36662306a36Sopenharmony_ci __le16 val[16]; 36762306a36Sopenharmony_ci} __packed; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistruct hermes_multicast { 37062306a36Sopenharmony_ci u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; 37162306a36Sopenharmony_ci} __packed; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci/* Timeouts */ 37462306a36Sopenharmony_ci#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistruct hermes; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci/* Functions to access hardware */ 37962306a36Sopenharmony_cistruct hermes_ops { 38062306a36Sopenharmony_ci int (*init)(struct hermes *hw); 38162306a36Sopenharmony_ci int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0, 38262306a36Sopenharmony_ci struct hermes_response *resp); 38362306a36Sopenharmony_ci int (*init_cmd_wait)(struct hermes *hw, u16 cmd, 38462306a36Sopenharmony_ci u16 parm0, u16 parm1, u16 parm2, 38562306a36Sopenharmony_ci struct hermes_response *resp); 38662306a36Sopenharmony_ci int (*allocate)(struct hermes *hw, u16 size, u16 *fid); 38762306a36Sopenharmony_ci int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen, 38862306a36Sopenharmony_ci u16 *length, void *buf); 38962306a36Sopenharmony_ci int (*read_ltv_pr)(struct hermes *hw, int bap, u16 rid, 39062306a36Sopenharmony_ci unsigned buflen, u16 *length, void *buf); 39162306a36Sopenharmony_ci int (*write_ltv)(struct hermes *hw, int bap, u16 rid, 39262306a36Sopenharmony_ci u16 length, const void *value); 39362306a36Sopenharmony_ci int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len, 39462306a36Sopenharmony_ci u16 id, u16 offset); 39562306a36Sopenharmony_ci int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, 39662306a36Sopenharmony_ci int len, u16 id, u16 offset); 39762306a36Sopenharmony_ci int (*read_pda)(struct hermes *hw, __le16 *pda, 39862306a36Sopenharmony_ci u32 pda_addr, u16 pda_len); 39962306a36Sopenharmony_ci int (*program_init)(struct hermes *hw, u32 entry_point); 40062306a36Sopenharmony_ci int (*program_end)(struct hermes *hw); 40162306a36Sopenharmony_ci int (*program)(struct hermes *hw, const char *buf, 40262306a36Sopenharmony_ci u32 addr, u32 len); 40362306a36Sopenharmony_ci void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags); 40462306a36Sopenharmony_ci void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags); 40562306a36Sopenharmony_ci void (*lock_irq)(spinlock_t *lock); 40662306a36Sopenharmony_ci void (*unlock_irq)(spinlock_t *lock); 40762306a36Sopenharmony_ci}; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci/* Basic control structure */ 41062306a36Sopenharmony_cistruct hermes { 41162306a36Sopenharmony_ci void __iomem *iobase; 41262306a36Sopenharmony_ci int reg_spacing; 41362306a36Sopenharmony_ci#define HERMES_16BIT_REGSPACING 0 41462306a36Sopenharmony_ci#define HERMES_32BIT_REGSPACING 1 41562306a36Sopenharmony_ci u16 inten; /* Which interrupts should be enabled? */ 41662306a36Sopenharmony_ci bool eeprom_pda; 41762306a36Sopenharmony_ci const struct hermes_ops *ops; 41862306a36Sopenharmony_ci void *priv; 41962306a36Sopenharmony_ci}; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/* Register access convenience macros */ 42262306a36Sopenharmony_ci#define hermes_read_reg(hw, off) \ 42362306a36Sopenharmony_ci (ioread16((hw)->iobase + ((off) << (hw)->reg_spacing))) 42462306a36Sopenharmony_ci#define hermes_write_reg(hw, off, val) \ 42562306a36Sopenharmony_ci (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing))) 42662306a36Sopenharmony_ci#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name) 42762306a36Sopenharmony_ci#define hermes_write_regn(hw, name, val) \ 42862306a36Sopenharmony_ci hermes_write_reg((hw), HERMES_##name, (val)) 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/* Function prototypes */ 43162306a36Sopenharmony_civoid hermes_struct_init(struct hermes *hw, void __iomem *address, 43262306a36Sopenharmony_ci int reg_spacing); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci/* Inline functions */ 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic inline int hermes_present(struct hermes *hw) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic inline void hermes_set_irqmask(struct hermes *hw, u16 events) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci hw->inten = events; 44462306a36Sopenharmony_ci hermes_write_regn(hw, INTEN, events); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic inline int hermes_enable_port(struct hermes *hw, int port) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 45062306a36Sopenharmony_ci 0, NULL); 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic inline int hermes_disable_port(struct hermes *hw, int port) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), 45662306a36Sopenharmony_ci 0, NULL); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci/* Initiate an INQUIRE command (tallies or scan). The result will come as an 46062306a36Sopenharmony_ci * information frame in __orinoco_ev_info() */ 46162306a36Sopenharmony_cistatic inline int hermes_inquire(struct hermes *hw, u16 rid) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1) 46762306a36Sopenharmony_ci#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2) 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* Note that for the next two, the count is in 16-bit words, not bytes */ 47062306a36Sopenharmony_cistatic inline void hermes_read_words(struct hermes *hw, int off, 47162306a36Sopenharmony_ci void *buf, unsigned count) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci off = off << hw->reg_spacing; 47462306a36Sopenharmony_ci ioread16_rep(hw->iobase + off, buf, count); 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic inline void hermes_write_bytes(struct hermes *hw, int off, 47862306a36Sopenharmony_ci const char *buf, unsigned count) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci off = off << hw->reg_spacing; 48162306a36Sopenharmony_ci iowrite16_rep(hw->iobase + off, buf, count >> 1); 48262306a36Sopenharmony_ci if (unlikely(count & 1)) 48362306a36Sopenharmony_ci iowrite8(buf[count - 1], hw->iobase + off); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic inline void hermes_clear_words(struct hermes *hw, int off, 48762306a36Sopenharmony_ci unsigned count) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci unsigned i; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci off = off << hw->reg_spacing; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci for (i = 0; i < count; i++) 49462306a36Sopenharmony_ci iowrite16(0, hw->iobase + off); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci#define HERMES_READ_RECORD(hw, bap, rid, buf) \ 49862306a36Sopenharmony_ci (hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) 49962306a36Sopenharmony_ci#define HERMES_READ_RECORD_PR(hw, bap, rid, buf) \ 50062306a36Sopenharmony_ci (hw->ops->read_ltv_pr((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) 50162306a36Sopenharmony_ci#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ 50262306a36Sopenharmony_ci (hw->ops->write_ltv((hw), (bap), (rid), \ 50362306a36Sopenharmony_ci HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid, 50662306a36Sopenharmony_ci u16 *word) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci __le16 rec; 50962306a36Sopenharmony_ci int err; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci err = HERMES_READ_RECORD(hw, bap, rid, &rec); 51262306a36Sopenharmony_ci *word = le16_to_cpu(rec); 51362306a36Sopenharmony_ci return err; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic inline int hermes_read_wordrec_pr(struct hermes *hw, int bap, u16 rid, 51762306a36Sopenharmony_ci u16 *word) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci __le16 rec; 52062306a36Sopenharmony_ci int err; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci err = HERMES_READ_RECORD_PR(hw, bap, rid, &rec); 52362306a36Sopenharmony_ci *word = le16_to_cpu(rec); 52462306a36Sopenharmony_ci return err; 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid, 52862306a36Sopenharmony_ci u16 word) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci __le16 rec = cpu_to_le16(word); 53162306a36Sopenharmony_ci return HERMES_WRITE_RECORD(hw, bap, rid, &rec); 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci#endif /* _HERMES_H */ 535