code:
/*-
 * Copyright (c) 1997, 1998, 1999
 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Bill Paul.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/dev/an/if_aironet_ieee.h 139749 2005-01-06 01:43:34Z imp $
 */

#ifndef _IF_AIRONET_IEEE_H
#define _IF_AIRONET_IEEE_H

/*
 * This header defines a simple command interface to the FreeBSD
 * Aironet driver (an) driver, which is used to set certain
 * device-specific parameters which can't be easily managed through
 * ifconfig(8). No, sysctl(2) is not the answer. I said a _simple_
 * interface, didn't I.
 */

#ifndef SIOCSAIRONET
#define SIOCSAIRONET	SIOCSIFGENERIC
#endif

#ifndef SIOCGAIRONET
#define SIOCGAIRONET	SIOCGIFGENERIC
#endif

/*
 * This is a make-predend RID value used only by the driver
 * to allow the user to set the speed.
 */
#define AN_RID_TX_SPEED		0x1234

/*
 * Technically I don't think there's a limit to a record
 * length. The largest record is the one that contains the CIS
 * data, which is 240 words long, so 256 should be a safe
 * value.
 */
#define AN_MAX_DATALEN	4096

struct an_req {
	u_int16_t	an_len;
	u_int16_t	an_type;
	u_int16_t	an_val[AN_MAX_DATALEN];
};

/*
 * Private LTV records (interpreted only by the driver). This is
 * a minor kludge to allow reading the interface statistics from
 * the driver.
 */
#define AN_RID_IFACE_STATS	0x0100
#define AN_RID_MGMT_XMIT	0x0200
#ifdef ANCACHE
#define AN_RID_ZERO_CACHE	0x0300
#define AN_RID_READ_CACHE	0x0400
#endif

#define AN_FCTL_VERS		0x0002
#define AN_FCTL_FTYPE		0x000C
#define AN_FCTL_STYPE		0x00F0
#define AN_FCTL_TODS		0x0100
#define AN_FCTL_FROMDS		0x0200
#define AN_FCTL_MOREFRAGS	0x0400
#define AN_FCTL_RETRY		0x0800
#define AN_FCTL_PM		0x1000
#define AN_FCTL_MOREDATA	0x2000
#define AN_FCTL_WEP		0x4000
#define AN_FCTL_ORDER		0x8000

#define AN_FTYPE_MGMT		0x0000
#define AN_FTYPE_CTL		0x0004
#define AN_FTYPE_DATA		0x0008

#define AN_STYPE_MGMT_ASREQ	0x0000	/* association request */
#define AN_STYPE_MGMT_ASRESP	0x0010	/* association response */
#define AN_STYPE_MGMT_REASREQ	0x0020	/* reassociation request */
#define AN_STYPE_MGMT_REASRESP	0x0030	/* reassociation response */
#define AN_STYPE_MGMT_PROBEREQ	0x0040	/* probe request */
#define AN_STYPE_MGMT_PROBERESP	0x0050	/* probe response */
#define AN_STYPE_MGMT_BEACON	0x0080	/* beacon */
#define AN_STYPE_MGMT_ATIM	0x0090	/* announcement traffic ind msg */
#define AN_STYPE_MGMT_DISAS	0x00A0	/* disassociation */
#define AN_STYPE_MGMT_AUTH	0x00B0	/* authentication */
#define AN_STYPE_MGMT_DEAUTH	0x00C0	/* deauthentication */

/*
 * Aironet IEEE signal strength cache
 *
 * driver keeps cache of last
 * MAXANCACHE packets to arrive including signal strength info.
 * daemons may read this via ioctl
 *
 * Each entry in the wi_sigcache has a unique macsrc.
 */
#ifdef ANCACHE
#define MAXANCACHE      10

struct an_sigcache {
	char	macsrc[6];	/* unique MAC address for entry */
	int	ipsrc;		/* ip address associated with packet */
	int	signal;		/* signal strength of the packet */
	int	noise;		/* noise value */
	int	quality;	/* quality of the packet */
};
#endif

/*
 * The card provides an 8-bit signal strength value (RSSI), which can
 * be converted to a dBm power value (or a percent) using a table in
 * the card's firmware (when available).  The tables are slightly
 * different in individual cards, even of the same model.  If the
 * table is not available, the mapping can be approximated by dBm =
 * RSSI - 100.  This approximation can be seen by plotting a few
 * tables, and also matches some info on the Intersil web site (I
 * think they make the RF front end for the cards.  However, the linux
 * driver uses the approximation dBm = RSSI/2 - 95.  I think that is
 * just wrong.
 */

struct an_rssi_entry {
	u_int8_t	an_rss_pct;
	u_int8_t	an_rss_dbm;
};

struct an_ltv_key {
	u_int16_t	an_len;
	u_int16_t	an_type;
	u_int16_t       kindex;
	u_int8_t        mac[6];
	u_int16_t       klen;
	u_int8_t        key[16];  /* 128-bit keys */
};

struct an_ltv_stats {
	u_int16_t		an_fudge;
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* 0xXX */
	u_int16_t		an_spacer;		/* 0x02 */
	u_int32_t		an_rx_overruns;		/* 0x04 */
	u_int32_t		an_rx_plcp_csum_errs;	/* 0x08 */
	u_int32_t		an_rx_plcp_format_errs;	/* 0x0C */
	u_int32_t		an_rx_plcp_len_errs;	/* 0x10 */
	u_int32_t		an_rx_mac_crc_errs;	/* 0x14 */
	u_int32_t		an_rx_mac_crc_ok;	/* 0x18 */
	u_int32_t		an_rx_wep_errs;		/* 0x1C */
	u_int32_t		an_rx_wep_ok;		/* 0x20 */
	u_int32_t		an_retry_long;		/* 0x24 */
	u_int32_t		an_retry_short;		/* 0x28 */
	u_int32_t		an_retry_max;		/* 0x2C */
	u_int32_t		an_no_ack;		/* 0x30 */
	u_int32_t		an_no_cts;		/* 0x34 */
	u_int32_t		an_rx_ack_ok;		/* 0x38 */
	u_int32_t		an_rx_cts_ok;		/* 0x3C */
	u_int32_t		an_tx_ack_ok;		/* 0x40 */
	u_int32_t		an_tx_rts_ok;		/* 0x44 */
	u_int32_t		an_tx_cts_ok;		/* 0x48 */
	u_int32_t		an_tx_lmac_mcasts;	/* 0x4C */
	u_int32_t		an_tx_lmac_bcasts;	/* 0x50 */
	u_int32_t		an_tx_lmac_ucast_frags;	/* 0x54 */
	u_int32_t		an_tx_lmac_ucasts;	/* 0x58 */
	u_int32_t		an_tx_beacons;		/* 0x5C */
	u_int32_t		an_rx_beacons;		/* 0x60 */
	u_int32_t		an_tx_single_cols;	/* 0x64 */
	u_int32_t		an_tx_multi_cols;	/* 0x68 */
	u_int32_t		an_tx_defers_no;	/* 0x6C */
	u_int32_t		an_tx_defers_prot;	/* 0x70 */
	u_int32_t		an_tx_defers_energy;	/* 0x74 */
	u_int32_t		an_rx_dups;		/* 0x78 */
	u_int32_t		an_rx_partial;		/* 0x7C */
	u_int32_t		an_tx_too_old;		/* 0x80 */
	u_int32_t		an_rx_too_old;		/* 0x84 */
	u_int32_t		an_lostsync_max_retries;/* 0x88 */
	u_int32_t		an_lostsync_missed_beacons;/* 0x8C */
	u_int32_t		an_lostsync_arl_exceeded;/*0x90 */
	u_int32_t		an_lostsync_deauthed;	/* 0x94 */
	u_int32_t		an_lostsync_disassociated;/*0x98 */
	u_int32_t		an_lostsync_tsf_timing;	/* 0x9C */
	u_int32_t		an_tx_host_mcasts;	/* 0xA0 */
	u_int32_t		an_tx_host_bcasts;	/* 0xA4 */
	u_int32_t		an_tx_host_ucasts;	/* 0xA8 */
	u_int32_t		an_tx_host_failed;	/* 0xAC */
	u_int32_t		an_rx_host_mcasts;	/* 0xB0 */
	u_int32_t		an_rx_host_bcasts;	/* 0xB4 */
	u_int32_t		an_rx_host_ucasts;	/* 0xB8 */
	u_int32_t		an_rx_host_discarded;	/* 0xBC */
	u_int32_t		an_tx_hmac_mcasts;	/* 0xC0 */
	u_int32_t		an_tx_hmac_bcasts;	/* 0xC4 */
	u_int32_t		an_tx_hmac_ucasts;	/* 0xC8 */
	u_int32_t		an_tx_hmac_failed;	/* 0xCC */
	u_int32_t		an_rx_hmac_mcasts;	/* 0xD0 */
	u_int32_t		an_rx_hmac_bcasts;	/* 0xD4 */
	u_int32_t		an_rx_hmac_ucasts;	/* 0xD8 */
	u_int32_t		an_rx_hmac_discarded;	/* 0xDC */
	u_int32_t		an_tx_hmac_accepted;	/* 0xE0 */
	u_int32_t		an_ssid_mismatches;	/* 0xE4 */
	u_int32_t		an_ap_mismatches;	/* 0xE8 */
	u_int32_t		an_rates_mismatches;	/* 0xEC */
	u_int32_t		an_auth_rejects;	/* 0xF0 */
	u_int32_t		an_auth_timeouts;	/* 0xF4 */
	u_int32_t		an_assoc_rejects;	/* 0xF8 */
	u_int32_t		an_assoc_timeouts;	/* 0xFC */
	u_int32_t		an_reason_outside_table;/* 0x100 */
	u_int32_t		an_reason1;		/* 0x104 */
	u_int32_t		an_reason2;		/* 0x108 */
	u_int32_t		an_reason3;		/* 0x10C */
	u_int32_t		an_reason4;		/* 0x110 */
	u_int32_t		an_reason5;		/* 0x114 */
	u_int32_t		an_reason6;		/* 0x118 */
	u_int32_t		an_reason7;		/* 0x11C */
	u_int32_t		an_reason8;		/* 0x120 */
	u_int32_t		an_reason9;		/* 0x124 */
	u_int32_t		an_reason10;		/* 0x128 */
	u_int32_t		an_reason11;		/* 0x12C */
	u_int32_t		an_reason12;		/* 0x130 */
	u_int32_t		an_reason13;		/* 0x134 */
	u_int32_t		an_reason14;		/* 0x138 */
	u_int32_t		an_reason15;		/* 0x13C */
	u_int32_t		an_reason16;		/* 0x140 */
	u_int32_t		an_reason17;		/* 0x144 */
	u_int32_t		an_reason18;		/* 0x148 */
	u_int32_t		an_reason19;		/* 0x14C */
	u_int32_t		an_rx_mgmt_pkts;	/* 0x150 */
	u_int32_t		an_tx_mgmt_pkts;	/* 0x154 */
	u_int32_t		an_rx_refresh_pkts;	/* 0x158 */
	u_int32_t		an_tx_refresh_pkts;	/* 0x15C */
	u_int32_t		an_rx_poll_pkts;	/* 0x160 */
	u_int32_t		an_tx_poll_pkts;	/* 0x164 */
	u_int32_t		an_host_retries;	/* 0x168 */
	u_int32_t		an_lostsync_hostreq;	/* 0x16C */
	u_int32_t		an_host_tx_bytes;	/* 0x170 */
	u_int32_t		an_host_rx_bytes;	/* 0x174 */
	u_int32_t		an_uptime_usecs;	/* 0x178 */
	u_int32_t		an_uptime_secs;		/* 0x17C */
	u_int32_t		an_lostsync_better_ap;	/* 0x180 */
	u_int32_t		an_rsvd[15];
};

/*
 * General configuration information.
 */
struct an_ltv_genconfig {
	/* General configuration. */
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* XXXX */
	u_int16_t		an_opmode;		/* 0x02 */
	u_int16_t		an_rxmode;		/* 0x04 */
	u_int16_t		an_fragthresh;		/* 0x06 */
	u_int16_t		an_rtsthresh;		/* 0x08 */
	u_int8_t		an_macaddr[6];		/* 0x0A */
	u_int8_t		an_rates[8];		/* 0x10 */
	u_int16_t		an_shortretry_limit;	/* 0x18 */
	u_int16_t		an_longretry_limit;	/* 0x1A */
	u_int16_t		an_tx_msdu_lifetime;	/* 0x1C */
	u_int16_t		an_rx_msdu_lifetime;	/* 0x1E */
	u_int16_t		an_stationary;		/* 0x20 */
	u_int16_t		an_ordering;		/* 0x22 */
	u_int16_t		an_devtype;		/* 0x24 */
	u_int16_t		an_rsvd0[5];		/* 0x26 */
	/* Scanning associating. */
	u_int16_t		an_scanmode;		/* 0x30 */
	u_int16_t		an_probedelay;		/* 0x32 */
	u_int16_t		an_probe_energy_timeout;/* 0x34 */
	u_int16_t		an_probe_response_timeout;/*0x36 */
	u_int16_t		an_beacon_listen_timeout;/*0x38 */
	u_int16_t		an_ibss_join_net_timeout;/*0x3A */
	u_int16_t		an_auth_timeout;	/* 0x3C */
	u_int16_t		an_authtype;		/* 0x3E */
	u_int16_t		an_assoc_timeout;	/* 0x40 */
	u_int16_t		an_specified_ap_timeout;/* 0x42 */
	u_int16_t		an_offline_scan_interval;/*0x44 */
	u_int16_t		an_offline_scan_duration;/*0x46 */
	u_int16_t		an_link_loss_delay;	/* 0x48 */
	u_int16_t		an_max_beacon_lost_time;/* 0x4A */
	u_int16_t		an_refresh_interval;	/* 0x4C */
	u_int16_t		an_rsvd1;		/* 0x4E */
	/* Power save operation */
	u_int16_t		an_psave_mode;		/* 0x50 */
	u_int16_t		an_sleep_for_dtims;	/* 0x52 */
	u_int16_t		an_listen_interval;	/* 0x54 */
	u_int16_t		an_fast_listen_interval;/* 0x56 */
	u_int16_t		an_listen_decay;	/* 0x58 */
	u_int16_t		an_fast_listen_decay;	/* 0x5A */
	u_int16_t		an_rsvd2[2];		/* 0x5C */
	/* Ad-hoc (or AP) operation. */
	u_int16_t		an_beacon_period;	/* 0x60 */
	u_int16_t		an_atim_duration;	/* 0x62 */
	u_int16_t		an_rsvd3;		/* 0x64 */
	u_int16_t		an_ds_channel;		/* 0x66 */
	u_int16_t		an_rsvd4;		/* 0x68 */
	u_int16_t		an_dtim_period;		/* 0x6A */
	u_int16_t		an_rsvd5[2];		/* 0x6C */
	/* Radio operation. */
	u_int16_t		an_radiotype;		/* 0x70 */
	u_int16_t		an_diversity;		/* 0x72 */
	u_int16_t		an_tx_power;		/* 0x74 */
	u_int16_t		an_rss_thresh;		/* 0x76 */
	u_int16_t		an_modulation_type;	/* 0x78 */
	u_int16_t		an_short_preamble;	/* 0x7A */
	u_int16_t		an_home_product;	/* 0x7C */
	u_int16_t		an_rsvd6;		/* 0x7E */
	/* Aironet extensions. */
	u_int8_t		an_nodename[16];	/* 0x80 */
	u_int16_t		an_arl_thresh;		/* 0x90 */
	u_int16_t		an_arl_decay;		/* 0x92 */
	u_int16_t		an_arl_delay;		/* 0x94 */
	u_int8_t		an_rsvd7;		/* 0x96 */
	u_int8_t		an_rsvd8;		/* 0x97 */
	u_int8_t		an_magic_packet_action;	/* 0x98 */
	u_int8_t		an_magic_packet_ctl;	/* 0x99 */
	u_int16_t		an_rsvd9;
	u_int16_t		an_spare[19];
};

#define AN_OPMODE_IBSS_ADHOC			0x0000
#define AN_OPMODE_INFRASTRUCTURE_STATION	0x0001
#define AN_OPMODE_AP				0x0002
#define AN_OPMODE_AP_REPEATER			0x0003
#define AN_OPMODE_UNMODIFIED_PAYLOAD		0x0100
#define AN_OPMODE_AIRONET_EXTENSIONS		0x0200
#define AN_OPMODE_AP_EXTENSIONS			0x0400

#define AN_RXMODE_BC_MC_ADDR			0x0000
#define AN_RXMODE_BC_ADDR			0x0001
#define AN_RXMODE_ADDR				0x0002
#define AN_RXMODE_80211_MONITOR_CURBSS		0x0003
#define AN_RXMODE_80211_MONITOR_ANYBSS		0x0004
#define AN_RXMODE_LAN_MONITOR_CURBSS		0x0005
#define AN_RXMODE_NO_8023_HEADER		0x0100
#define AN_RXMODE_NORMALIZED_RSSI		0x0200

#define AN_RATE_1MBPS				0x0002
#define AN_RATE_2MBPS				0x0004
#define AN_RATE_5_5MBPS				0x000B
#define AN_RATE_11MBPS				0x0016

#define AN_DEVTYPE_PC4500			0x0065
#define AN_DEVTYPE_PC4800			0x006D

#define AN_SCANMODE_ACTIVE			0x0000
#define AN_SCANMODE_PASSIVE			0x0001
#define AN_SCANMODE_AIRONET_ACTIVE		0x0002

#define AN_AUTHTYPE_NONE			0x0000
#define AN_AUTHTYPE_OPEN			0x0001
#define AN_AUTHTYPE_SHAREDKEY			0x0002
#define AN_AUTHTYPE_MASK                        0x00ff
#define AN_AUTHTYPE_ENABLE			0x0100
#define AN_AUTHTYPE_PRIVACY_IN_USE		0x0100
#define AN_AUTHTYPE_ALLOW_UNENCRYPTED		0x0200
#define AN_AUTHTYPE_LEAP			0x1000

#define AN_PSAVE_NONE				0x0000
#define AN_PSAVE_CAM				0x0001
#define AN_PSAVE_PSP				0x0002
#define AN_PSAVE_PSP_CAM			0x0003

#define AN_RADIOTYPE_80211_FH			0x0001
#define AN_RADIOTYPE_80211_DS			0x0002
#define AN_RADIOTYPE_LM2000_DS			0x0004

#define AN_DIVERSITY_FACTORY_DEFAULT		0x0000
#define AN_DIVERSITY_ANTENNA_1_ONLY		0x0001
#define AN_DIVERSITY_ANTENNA_2_ONLY		0x0002
#define AN_DIVERSITY_ANTENNA_1_AND_2		0x0003

#define AN_TXPOWER_FACTORY_DEFAULT		0x0000
#define AN_TXPOWER_50MW				50
#define AN_TXPOWER_100MW			100
#define AN_TXPOWER_250MW			250

#define AN_HOME_NETWORK				0x0001
#define AN_HOME_INSTALL_AP			0x0002

/*
 * Valid SSID list. You can specify up to three SSIDs denoting
 * the service sets that you want to join. The first SSID always
 * defaults to "tsunami" which is a handy way to detect the
 * card.
 */

struct an_ltv_ssidlist {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int16_t		an_ssid1_len;
	char			an_ssid1[32];
	u_int16_t		an_ssid2_len;
	char			an_ssid2[32];
	u_int16_t		an_ssid3_len;
	char			an_ssid3[32];
};

struct an_ltv_ssid_entry{
	u_int16_t		an_len;
	char			an_ssid[32];
};

#define MAX_SSIDS 25
struct an_ltv_ssidlist_new {
	u_int16_t		an_len;
	u_int16_t		an_type;
	struct an_ltv_ssid_entry an_entry[MAX_SSIDS];
};

/*
 * Valid AP list.
 */
struct an_ltv_aplist {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int8_t		an_ap1[8];
	u_int8_t		an_ap2[8];
	u_int8_t		an_ap3[8];
	u_int8_t		an_ap4[8];
};

/*
 * Driver name.
 */
struct an_ltv_drvname {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int8_t		an_drvname[16];
};

/*
 * Frame encapsulation.
 */
struct an_rid_encap {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int16_t		an_ethertype_default;
	u_int16_t		an_action_default;
	u_int16_t		an_ethertype0;
	u_int16_t		an_action0;
	u_int16_t		an_ethertype1;
	u_int16_t		an_action1;
	u_int16_t		an_ethertype2;
	u_int16_t		an_action2;
	u_int16_t		an_ethertype3;
	u_int16_t		an_action3;
	u_int16_t		an_ethertype4;
	u_int16_t		an_action4;
	u_int16_t		an_ethertype5;
	u_int16_t		an_action5;
	u_int16_t		an_ethertype6;
	u_int16_t		an_action6;
};

#define AN_ENCAP_ACTION_RX	0x0001
#define AN_ENCAP_ACTION_TX	0x0002

#define AN_RXENCAP_NONE		0x0000
#define AN_RXENCAP_RFC1024	0x0001

#define AN_TXENCAP_RFC1024	0x0000
#define AN_TXENCAP_80211	0x0002

/*
 * Card capabilities (read only).
 */
struct an_ltv_caps {
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* XXXX */
	u_int8_t		an_oui[3];		/* 0x02 */
	u_int8_t		an_rsvd0;		/* 0x05 */
	u_int16_t		an_prodnum;		/* 0x06 */
	u_int8_t		an_manufname[32];	/* 0x08 */
	u_int8_t		an_prodname[16];	/* 0x28 */
	u_int8_t		an_prodvers[8];		/* 0x38 */
	u_int8_t		an_oemaddr[6];		/* 0x40 */
	u_int8_t		an_aironetaddr[6];	/* 0x46 */
	u_int16_t		an_radiotype;		/* 0x4C */
	u_int16_t		an_regdomain;		/* 0x4E */
	u_int8_t		an_callid[6];		/* 0x50 */
	u_int8_t		an_rates[8];		/* 0x56 */
	u_int8_t		an_rx_diversity;	/* 0x5E */
	u_int8_t		an_tx_diversity;	/* 0x5F */
	u_int16_t		an_tx_powerlevels[8];	/* 0x60 */
	u_int16_t		an_hwrev;		/* 0x70 */
	u_int16_t		an_hwcaps;		/* 0x72 */
	u_int16_t		an_temprange;		/* 0x74 */
	u_int16_t		an_fwrev;		/* 0x76 */
	u_int16_t		an_fwsubrev;		/* 0x78 */
	u_int16_t		an_ifacerev;		/* 0x7A */
	u_int16_t		an_softcaps;		/* 0x7C */
	u_int16_t		an_bootblockrev;	/* 0x7E */
	u_int16_t		an_req_hw_support;	/* 0x80 */
	u_int16_t		an_unknown[31];		/* 0x82 */
};

/*
 * Access point (read only)
 */
struct an_ltv_apinfo {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int16_t		an_tim_addr;
	u_int16_t		an_airo_addr;
};

/*
 * Radio info (read only).
 */
struct an_ltv_radioinfo {
	u_int16_t		an_len;
	u_int16_t		an_type;
	/* ??? */
};

/*
 * RSSI map.  If available in the card's firmware, this can be used to
 * convert the 8-bit RSSI values from the card into dBm.
 */
struct an_ltv_rssi_map {
	u_int16_t		an_len;
	u_int16_t		an_type;
	struct an_rssi_entry	an_entries[256];
};

/*
 * Status (read only). Note: the manual claims this RID is 108 bytes
 * long (0x6A is the last datum, which is 2 bytes long) however when
 * this RID is read from the NIC, it returns a length of 110. To be
 * on the safe side, this structure is padded with an extra 16-bit
 * word. (There is a misprint in the manual which says the macaddr
 * field is 8 bytes long.)
 *
 * Also, the channel_set and current_channel fields appear to be
 * reversed. Either that, or the hop_period field is unused.
 */
struct an_ltv_status {
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* 0xXX */
	u_int8_t		an_macaddr[6];		/* 0x02 */
	u_int16_t		an_opmode;		/* 0x08 */
	u_int16_t		an_errcode;		/* 0x0A */
	u_int16_t		an_signal_quality;	/* 0x0C */
	u_int16_t		an_ssidlen;		/* 0x0E */
	u_int8_t		an_ssid[32];		/* 0x10 */
	u_int8_t		an_ap_name[16];		/* 0x30 */
	u_int8_t		an_cur_bssid[6];	/* 0x40 */
	u_int8_t		an_prev_bssid1[6];	/* 0x46 */
	u_int8_t		an_prev_bssid2[6];	/* 0x4C */
	u_int8_t		an_prev_bssid3[6];	/* 0x52 */
	u_int16_t		an_beacon_period;	/* 0x58 */
	u_int16_t		an_dtim_period;		/* 0x5A */
	u_int16_t		an_atim_duration;	/* 0x5C */
	u_int16_t		an_hop_period;		/* 0x5E */
	u_int16_t		an_cur_channel;		/* 0x62 */
	u_int16_t		an_channel_set;		/* 0x60 */
	u_int16_t		an_hops_to_backbone;	/* 0x64 */
	u_int16_t		an_ap_total_load;	/* 0x66 */
	u_int16_t		an_our_generated_load;	/* 0x68 */
	u_int16_t		an_accumulated_arl;	/* 0x6A */
	u_int16_t		an_cur_signal_quality;	/* 0x6C */
	u_int16_t		an_current_tx_rate;	/* 0x6E */
	u_int16_t		an_ap_device;		/* 0x70 */
	u_int16_t		an_normalized_strength;	/* 0x72 */
	u_int16_t		an_short_pre_in_use;	/* 0x74 */
	u_int8_t		an_ap_ip_addr[4];	/* 0x76 */
	u_int8_t		an_noise_prev_sec_pc;   /* 0x7A */
	u_int8_t		an_noise_prev_sec_db;   /* 0x7B */
	u_int8_t		an_avg_noise_prev_min_pc;       /* 0x7C */
	u_int8_t		an_avg_noise_prev_min_db;       /* 0x7D */
	u_int8_t		an_max_noise_prev_min_pc;       /* 0x7E */
	u_int8_t		an_max_noise_prev_min_db;       /* 0x7F */
	u_int16_t		an_spare[18];
};

#define AN_STATUS_OPMODE_CONFIGURED		0x0001
#define AN_STATUS_OPMODE_MAC_ENABLED		0x0002
#define AN_STATUS_OPMODE_RX_ENABLED		0x0004
#define AN_STATUS_OPMODE_IN_SYNC		0x0010
#define AN_STATUS_OPMODE_ASSOCIATED		0x0020
#define AN_STATUS_OPMODE_LEAP			0x0040
#define AN_STATUS_OPMODE_ERROR			0x8000

/*
 * WEP Key
 */
struct an_ltv_wepkey {
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* 0xXX */
	u_int16_t		an_key_index;		/* 0x02 */
	u_int8_t		an_mac_addr[6];		/* 0x04 */
	u_int16_t		an_key_len;		/* 0x0A */
	u_int8_t		an_key[13];		/* 0x0C */
};

/*
 * Receive frame structure.
 */
struct an_rxframe {
	u_int32_t		an_rx_time;		/* 0x00 */
	u_int16_t		an_rx_status;		/* 0x04 */
	u_int16_t		an_rx_payload_len;	/* 0x06 */
	u_int8_t		an_rsvd0;		/* 0x08 */
	u_int8_t		an_rx_signal_strength;	/* 0x09 */
	u_int8_t		an_rx_rate;		/* 0x0A */
	u_int8_t		an_rx_chan;		/* 0x0B */
	u_int8_t		an_rx_assoc_cnt;	/* 0x0C */
	u_int8_t		an_rsvd1[3];		/* 0x0D */
	u_int8_t		an_plcp_hdr[4];		/* 0x10 */
	u_int16_t		an_frame_ctl;		/* 0x14 */
	u_int16_t		an_duration;		/* 0x16 */
	u_int8_t		an_addr1[6];		/* 0x18 */
	u_int8_t		an_addr2[6];		/* 0x1E */
	u_int8_t		an_addr3[6];		/* 0x24 */
	u_int16_t		an_seq_ctl;		/* 0x2A */
	u_int8_t		an_addr4[6];		/* 0x2C */
	u_int8_t		an_gaplen;		/* 0x32 */
} __packed;

/* Do not modify this unless you are modifying LEAP itself */
#define LEAP_USERNAME_MAX 32
#define LEAP_PASSWORD_MAX 32

/*
 * LEAP Username
 */
struct an_ltv_leap_username {
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* 0xXX */
	u_int16_t		an_username_len;	/* 0x02 */
	u_int8_t		an_username[LEAP_USERNAME_MAX];	/* 0x04 */
};

/*
 * LEAP Password
 */
struct an_ltv_leap_password {
	u_int16_t		an_len;			/* 0x00 */
	u_int16_t		an_type;		/* 0xXX */
	u_int16_t		an_password_len;	/* 0x02 */
	u_int8_t		an_password[LEAP_PASSWORD_MAX];	/* 0x04 */
};

/*
 * These are all the LTV record types that we can read or write
 * from the Aironet. Not all of them are temendously useful, but I
 * list as many as I know about here for completeness.
 */

/*
 * Configuration (read/write)
 */
#define AN_RID_GENCONFIG	0xFF10	/* General configuration info */
#define AN_RID_SSIDLIST		0xFF11	/* Valid SSID list */
#define AN_RID_APLIST		0xFF12	/* Valid AP list */
#define AN_RID_DRVNAME		0xFF13	/* ID name of this node for diag */
#define AN_RID_ENCAPPROTO	0xFF14	/* Payload encapsulation type */
#define AN_RID_WEP_TEMP	        0xFF15  /* Temporary Key */
#define AN_RID_WEP_PERM	        0xFF16  /* Perminant Key */
#define AN_RID_ACTUALCFG	0xFF20	/* Current configuration settings */

/*
 * Reporting (read only)
 */
#define AN_RID_CAPABILITIES	0xFF00	/* PC 4500/4800 capabilities */
#define AN_RID_AP_INFO		0xFF01	/* Access point info */
#define AN_RID_RADIO_INFO	0xFF02	/* Radio info */
#define AN_RID_RSSI_MAP         0xFF04  /* RSSI <-> dBm table */
#define AN_RID_STATUS		0xFF50	/* Current status info */
#define AN_RID_BEACONS_HST	0xFF51
#define AN_RID_BUSY_HST		0xFF52
#define AN_RID_RETRIES_HST	0xFF53

/*
 * Statistics
 */
#define AN_RID_16BITS_CUM	0xFF60	/* Cumulative 16-bit stats counters */
#define AN_RID_16BITS_DELTA	0xFF61	/* 16-bit stats (since last clear) */
#define AN_RID_16BITS_DELTACLR	0xFF62	/* 16-bit stats, clear on read */
#define AN_RID_32BITS_CUM	0xFF68	/* Cumulative 32-bit stats counters */
#define AN_RID_32BITS_DELTA	0xFF69	/* 32-bit stats (since last clear) */
#define AN_RID_32BITS_DELTACLR	0xFF6A	/* 32-bit stats, clear on read */

/*
 * LEAP
 */

#define AN_RID_LEAPUSERNAME	0xFF23	/* Username */
#define AN_RID_LEAPPASSWORD	0xFF24	/* Password */

/*
 * OTHER Unknonwn for now
 */

#define AN_RID_MOD		0xFF17
#define AN_RID_OPTIONS		0xFF18
#define AN_RID_FACTORY_CONFIG	0xFF18

/*
 *   FreeBSD fake RID
 */

#define AN_RID_MONITOR_MODE	0x0001	/* Set monitor mode for driver */
#define AN_MONITOR			 1
#define AN_MONITOR_ANY_BSS		 2
#define AN_MONITOR_INCLUDE_BEACON	 4
#define AN_MONITOR_AIRONET_HEADER	 8

#define DLT_AIRONET_HEADER 	120	/* Has been allocated at tcpdump.org */

/*
 * from the Linux driver from Cisco ... no copyright header.
 * Removed duplicated information that already existed in the FreeBSD driver
 * provides emulation of the Cisco extensions to the Linux Aironet driver.
 */

/*
 * Ioctl constants to be used in airo_ioctl.command
 */

#define	AIROGCAP	0	/* Capability rid */
#define AIROGCFG	1	/* USED A LOT  */
#define AIROGSLIST	2	/* System ID list  */
#define AIROGVLIST	3	/* List of specified AP's */
#define AIROGDRVNAM	4	/* NOTUSED */
#define AIROGEHTENC	5	/* NOTUSED */
#define AIROGWEPKTMP	6
#define AIROGWEPKNV	7
#define AIROGSTAT	8
#define AIROGSTATSC32	9
#define AIROGSTATSD32	10

/*
 * Leave gap of 40 commands after AIROGSTATSD32
 */

#define AIROPCAP	AIROGSTATSD32	+ 40
#define AIROPVLIST	AIROPCAP	+ 1
#define AIROPSLIST	AIROPVLIST	+ 1
#define AIROPCFG	AIROPSLIST	+ 1
#define AIROPSIDS	AIROPCFG	+ 1
#define AIROPAPLIST	AIROPSIDS	+ 1
#define AIROPMACON	AIROPAPLIST	+ 1	/* Enable mac  */
#define AIROPMACOFF	AIROPMACON	+ 1	/* Disable mac */
#define AIROPSTCLR	AIROPMACOFF	+ 1
#define AIROPWEPKEY	AIROPSTCLR	+ 1
#define AIROPWEPKEYNV	AIROPWEPKEY	+ 1
#define AIROPLEAPPWD	AIROPWEPKEYNV	+ 1
#define AIROPLEAPUSR	AIROPLEAPPWD	+ 1

/*
 * Another gap of 40 commands before flash codes
 */

#define AIROFLSHRST	AIROPWEPKEYNV	+ 40
#define AIROFLSHGCHR	AIROFLSHRST	+ 1
#define AIROFLSHSTFL	AIROFLSHGCHR	+ 1
#define AIROFLSHPCHR	AIROFLSHSTFL	+ 1
#define AIROFLPUTBUF	AIROFLSHPCHR	+ 1
#define AIRORESTART	AIROFLPUTBUF	+ 1

/*
 * Struct to enable up to 65535 ioctl's
 */

#define AIROMAGIC	0xa55a

typedef struct aironet_ioctl {
  unsigned short command;	/* What to do */
  unsigned short len;		/* Len of data */
  unsigned char *data;		/* d-data */
} airo_ioctl;

#endif


code:
/*-
 * Copyright (c) 1997, 1998, 1999
 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Bill Paul.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/dev/an/if_anreg.h 199757 2009-11-24 16:57:35Z jhb $
 */

#define AN_TIMEOUT	65536

/* Default network name: <empty string> */
#define AN_DEFAULT_NETNAME	""

/* The nodename must be less than 16 bytes */
#define AN_DEFAULT_NODENAME	"FreeBSD"

#define AN_DEFAULT_IBSS		"FreeBSD IBSS"

/*
 * register space access macros
 */
#define CSR_WRITE_2(sc, reg, val)	bus_write_2(sc->port_res, reg, val)

#define CSR_READ_2(sc, reg)		bus_read_2(sc->port_res, reg)

#define CSR_WRITE_1(sc, reg, val)	bus_write_1(sc->port_res, reg, val)

#define CSR_READ_1(sc, reg)		bus_read_1(sc->port_res, reg)

/*
 * memory space access macros
 */
#define CSR_MEM_WRITE_2(sc, reg, val)	bus_write_2(sc->mem_res, reg, val)

#define CSR_MEM_READ_2(sc, reg)		bus_read_2(sc->mem_res, reg)

#define CSR_MEM_WRITE_1(sc, reg, val)	bus_write_1(sc->mem_res, reg, val)

#define CSR_MEM_READ_1(sc, reg)		bus_read_1(sc->mem_res, reg)

/*
 * aux. memory space access macros
 */
#define CSR_MEM_AUX_WRITE_4(sc, reg, val)	\
	bus_write_4(sc->mem_aux_res, reg, val)

#define CSR_MEM_AUX_READ_4(sc, reg)		\
	bus_read_4(sc->mem_aux_res, reg)

#define CSR_MEM_AUX_WRITE_1(sc, reg, val)	\
	bus_write_1(sc->mem_aux_res, reg, val)

#define CSR_MEM_AUX_READ_1(sc, reg)		\
	bus_read_1(sc->mem_aux_res, reg)

/*
 * Size of Aironet I/O space.
 */
#define AN_IOSIZ		0x40

/*
 * Size of aux. memory space ... probably not needed DJA
 */
#define AN_AUX_MEM_SIZE		(256 * 1024)

/*
 * Hermes register definitions and what little I know about them.
 */

/* Hermes command/status registers. */
#define AN_COMMAND(x)		(x ? 0x00 : 0x00)
#define AN_PARAM0(x)		(x ? 0x04 : 0x02)
#define AN_PARAM1(x)		(x ? 0x08 : 0x04)
#define AN_PARAM2(x)		(x ? 0x0c : 0x06)
#define AN_STATUS(x)		(x ? 0x10 : 0x08)
#define AN_RESP0(x)		(x ? 0x14 : 0x0A)
#define AN_RESP1(x)		(x ? 0x18 : 0x0C)
#define AN_RESP2(x)		(x ? 0x1c : 0x0E)
#define AN_LINKSTAT(x)		(x ? 0x20 : 0x10)

/* Command register */
#define AN_CMD_BUSY		0x8000 /* busy bit */
#define AN_CMD_NO_ACK		0x0080 /* don't acknowledge command */
#define AN_CMD_CODE_MASK	0x003F
#define AN_CMD_QUAL_MASK	0x7F00

/* Command codes */
#define AN_CMD_NOOP		0x0000 /* no-op */
#define AN_CMD_ENABLE		0x0001 /* enable */
#define AN_CMD_DISABLE		0x0002 /* disable */
#define AN_CMD_FORCE_SYNCLOSS	0x0003 /* force loss of sync */
#define AN_CMD_FW_RESTART	0x0004 /* firmware restart */
#define AN_CMD_HOST_SLEEP	0x0005
#define AN_CMD_MAGIC_PKT	0x0006
#define AN_CMD_READCFG		0x0008
#define AN_CMD_SET_MODE		0x0009
#define AN_CMD_ALLOC_MEM	0x000A /* allocate NIC memory */
#define AN_CMD_TX		0x000B /* transmit */
#define AN_CMD_DEALLOC_MEM	0x000C
#define AN_CMD_NOOP2		0x0010
#define AN_CMD_ALLOC_DESC	0x0020
#define AN_CMD_ACCESS		0x0021
#define AN_CMD_ALLOC_BUF	0x0028
#define AN_CMD_PSP_NODES	0x0030
#define AN_CMD_SET_PHYREG	0x003E
#define AN_CMD_TX_TEST		0x003F
#define AN_CMD_SLEEP		0x0085
#define AN_CMD_SAVECFG		0x0108

/*
 * MPI 350 DMA descriptor information
 */
#define AN_DESCRIPTOR_TX	0x01
#define AN_DESCRIPTOR_RX	0x02
#define AN_DESCRIPTOR_TXCMP	0x04
#define AN_DESCRIPTOR_HOSTWRITE	0x08
#define AN_DESCRIPTOR_HOSTREAD	0x10
#define AN_DESCRIPTOR_HOSTRW	0x20

#define AN_MAX_RX_DESC 1
#define AN_MAX_TX_DESC 1
#define AN_HOSTBUFSIZ 1840

struct an_card_rid_desc
{
	unsigned	an_rid:16;
	unsigned	an_len:15;
	unsigned	an_valid:1;
	u_int64_t	an_phys;
};

struct an_card_rx_desc
{
	unsigned	an_ctrl:15;
	unsigned	an_done:1;
	unsigned	an_len:15;
	unsigned	an_valid:1;
	u_int64_t	an_phys;
};

struct an_card_tx_desc
{
	unsigned	an_offset:15;
	unsigned	an_eoc:1;
	unsigned	an_len:15;
	unsigned	an_valid:1;
	u_int64_t	an_phys;
};

#define AN_RID_BUFFER_SIZE	AN_MAX_DATALEN
#define AN_RX_BUFFER_SIZE	AN_HOSTBUFSIZ
#define AN_TX_BUFFER_SIZE	AN_HOSTBUFSIZ
/*#define AN_HOST_DESC_OFFSET	0xC sort of works */
#define AN_HOST_DESC_OFFSET	0x800
#define AN_RX_DESC_OFFSET  (AN_HOST_DESC_OFFSET + \
    sizeof(struct an_card_rid_desc))
#define AN_TX_DESC_OFFSET (AN_RX_DESC_OFFSET + \
    (AN_MAX_RX_DESC * sizeof(struct an_card_rx_desc)))

struct an_command {
	u_int16_t	an_cmd;
	u_int16_t	an_parm0;
	u_int16_t	an_parm1;
	u_int16_t	an_parm2;
};

struct an_reply {
	u_int16_t	an_status;
	u_int16_t	an_resp0;
	u_int16_t	an_resp1;
	u_int16_t	an_resp2;
};

/*
 * Reclaim qualifier bit, applicable to the
 * TX command.
 */
#define AN_RECLAIM		0x0100 /* reclaim NIC memory */

/*
 * ACCESS command qualifier bits.
 */
#define AN_ACCESS_READ		0x0000
#define AN_ACCESS_WRITE		0x0100

/*
 * PROGRAM command qualifier bits.
 */
#define AN_PROGRAM_DISABLE	0x0000
#define AN_PROGRAM_ENABLE_RAM	0x0100
#define AN_PROGRAM_ENABLE_NVRAM	0x0200
#define AN_PROGRAM_NVRAM	0x0300

/* Status register values */
#define AN_STAT_CMD_CODE	0x003F
#define AN_STAT_CMD_RESULT	0x7F00

/* Linkstat register */
#define AN_LINKSTAT_ASSOCIATED		0x0400
#define AN_LINKSTAT_AUTHFAIL		0x0300
#define AN_LINKSTAT_ASSOC_FAIL		0x8400
#define AN_LINKSTAT_DISASSOC		0x8200
#define AN_LINKSTAT_DEAUTH		0x8100
#define AN_LINKSTAT_SYNCLOST_TSF	0x8004
#define AN_LINKSTAT_SYNCLOST_HOSTREQ	0x8003
#define AN_LINKSTAT_SYNCLOST_AVGRETRY	0x8002
#define AN_LINKSTAT_SYNCLOST_MAXRETRY	0x8001
#define AN_LINKSTAT_SYNCLOST_MISSBEACON	0x8000

/* memory handle management registers */
#define AN_RX_FID		0x20
#define AN_ALLOC_FID		0x22
#define AN_TX_CMP_FID(x)	(x ? 0x1a : 0x24)

/*
 * Buffer Access Path (BAP) registers.
 * These are I/O channels. I believe you can use each one for
 * any desired purpose independently of the other. In general
 * though, we use BAP1 for reading and writing LTV records and
 * reading received data frames, and BAP0 for writing transmit
 * frames. This is a convention though, not a rule.
 */
#define AN_SEL0			0x18
#define AN_SEL1			0x1A
#define AN_OFF0			0x1C
#define AN_OFF1			0x1E
#define AN_DATA0		0x36
#define AN_DATA1		0x38
#define AN_BAP0			AN_DATA0
#define AN_BAP1			AN_DATA1

#define AN_OFF_BUSY		0x8000
#define AN_OFF_ERR		0x4000
#define AN_OFF_DONE		0x2000
#define AN_OFF_DATAOFF		0x0FFF

/* Event registers */
#define AN_EVENT_STAT(x)	(x ? 0x60 : 0x30)	/* Event status */
#define AN_INT_EN(x)		(x ? 0x64 : 0x32)	/* Interrupt enable/
							   disable */
#define AN_EVENT_ACK(x)		(x ? 0x68 : 0x34)	/* Ack event */

/* Events */
#define AN_EV_CLR_STUCK_BUSY	0x4000	/* clear stuck busy bit */
#define AN_EV_WAKEREQUEST	0x2000	/* awaken from PSP mode */
#define AN_EV_MIC		0x1000	/* Message Integrity Check*/
#define AN_EV_AWAKE		0x0100	/* station woke up from PSP mode*/
#define AN_EV_LINKSTAT		0x0080	/* link status available */
#define AN_EV_CMD		0x0010	/* command completed */
#define AN_EV_ALLOC		0x0008	/* async alloc/reclaim completed */
#define AN_EV_TX_CPY		0x0400
#define AN_EV_TX_EXC		0x0004	/* async xmit completed with failure */
#define AN_EV_TX		0x0002	/* async xmit completed succesfully */
#define AN_EV_RX		0x0001	/* async rx completed */

#define AN_INTRS(x)	\
	( x ? (AN_EV_RX|AN_EV_TX|AN_EV_TX_EXC|AN_EV_TX_CPY|AN_EV_ALLOC \
	       |AN_EV_LINKSTAT|AN_EV_MIC) \
	  : \
	      (AN_EV_RX|AN_EV_TX|AN_EV_TX_EXC|AN_EV_ALLOC \
	       |AN_EV_LINKSTAT|AN_EV_MIC) \
	      )

/* Host software registers */
#define AN_SW0(x)		(x ? 0x50 : 0x28)
#define AN_SW1(x)		(x ? 0x54 : 0x2A)
#define AN_SW2(x)		(x ? 0x58 : 0x2C)
#define AN_SW3(x)		(x ? 0x5c : 0x2E)

#define AN_CNTL			0x14

#define AN_CNTL_AUX_ENA		0xC000
#define AN_CNTL_AUX_ENA_STAT	0xC000
#define AN_CNTL_AUX_DIS_STAT	0x0000
#define AN_CNTL_AUX_ENA_CNTL	0x8000
#define AN_CNTL_AUX_DIS_CNTL	0x4000

#define AN_AUX_PAGE		0x3A
#define AN_AUX_OFFSET		0x3C
#define AN_AUX_DATA		0x3E

/*
 * Length, Type, Value (LTV) record definitions and RID values.
 */
struct an_ltv_gen {
	u_int16_t		an_len;
	u_int16_t		an_type;
	u_int16_t		an_val;
};

#define AN_DEF_SSID_LEN		7
#define AN_DEF_SSID		"tsunami"

#define AN_RXGAP_MAX	8

/*
 * Transmit frame structure.
 */
struct an_txframe {
	u_int32_t		an_tx_sw;		/* 0x00 */
	u_int16_t		an_tx_status;		/* 0x04 */
	u_int16_t		an_tx_payload_len;	/* 0x06 */
	u_int16_t		an_tx_ctl;		/* 0x08 */
	u_int16_t		an_tx_assoc_id;		/* 0x0A */
	u_int16_t		an_tx_retry;		/* 0x0C */
	u_int8_t		an_tx_assoc_cnt;	/* 0x0E */
	u_int8_t		an_tx_rate;		/* 0x0F */
	u_int8_t		an_tx_max_long_retries;	/* 0x10 */
	u_int8_t		an_tx_max_short_retries; /*0x11 */
	u_int8_t		an_rsvd0[2];		/* 0x12 */
	u_int16_t		an_frame_ctl;		/* 0x14 */
	u_int16_t		an_duration;		/* 0x16 */
	u_int8_t		an_addr1[6];		/* 0x18 */
	u_int8_t		an_addr2[6];		/* 0x1E */
	u_int8_t		an_addr3[6];		/* 0x24 */
	u_int16_t		an_seq_ctl;		/* 0x2A */
	u_int8_t		an_addr4[6];		/* 0x2C */
	u_int8_t		an_gaplen;		/* 0x32 */
} __packed;

struct an_rxframe_802_3 {
        u_int16_t		an_rx_802_3_status;     /* 0x34 */
	u_int16_t		an_rx_802_3_payload_len;/* 0x36 */
	u_int8_t		an_rx_dst_addr[6];      /* 0x38 */
	u_int8_t		an_rx_src_addr[6];      /* 0x3E */
};
#define AN_RXGAP_MAX	8

struct an_txframe_802_3 {
/*
 * Transmit 802.3 header structure.
 */
        u_int16_t		an_tx_802_3_status;     /* 0x34 */
	u_int16_t		an_tx_802_3_payload_len;/* 0x36 */
	u_int8_t		an_tx_dst_addr[6];      /* 0x38 */
	u_int8_t		an_tx_src_addr[6];      /* 0x3E */
};

#define AN_TXSTAT_EXCESS_RETRY	0x0002
#define AN_TXSTAT_LIFE_EXCEEDED	0x0004
#define AN_TXSTAT_AID_FAIL	0x0008
#define AN_TXSTAT_MAC_DISABLED	0x0010
#define AN_TXSTAT_ASSOC_LOST	0x0020

#define AN_TXCTL_RSVD		0x0001
#define AN_TXCTL_TXOK_INTR	0x0002
#define AN_TXCTL_TXERR_INTR	0x0004
#define AN_TXCTL_HEADER_TYPE	0x0008
#define AN_TXCTL_PAYLOAD_TYPE	0x0010
#define AN_TXCTL_NORELEASE	0x0020
#define AN_TXCTL_NORETRIES	0x0040
#define AN_TXCTL_CLEAR_AID	0x0080
#define AN_TXCTL_STRICT_ORDER	0x0100
#define AN_TXCTL_USE_RTS	0x0200

#define AN_HEADERTYPE_8023	0x0000
#define AN_HEADERTYPE_80211	0x0008

#define AN_PAYLOADTYPE_ETHER	0x0000
#define AN_PAYLOADTYPE_LLC	0x0010

#define AN_TXCTL_80211		(AN_HEADERTYPE_80211|AN_PAYLOADTYPE_LLC)

#define AN_TXCTL_8023		(AN_HEADERTYPE_8023|AN_PAYLOADTYPE_ETHER)

/*
 * Additions to transmit control bits for MPI350
 */
#define	AN_TXCTL_HW(x)	\
	( x ? (AN_TXCTL_NORELEASE) \
	  : \
	      (AN_TXCTL_TXOK_INTR|AN_TXCTL_TXERR_INTR|AN_TXCTL_NORELEASE) \
	      )

#define AN_TXGAP_80211		0
#define AN_TXGAP_8023		0

struct an_802_3_hdr {
	u_int16_t		an_8023_status;
	u_int16_t		an_8023_payload_len;
	u_int8_t		an_8023_dst_addr[6];
	u_int8_t		an_8023_src_addr[6];
	u_int16_t		an_8023_dat[3];	/* SNAP header */
	u_int16_t		an_8023_type;
};

struct an_snap_hdr {
	u_int16_t		an_snap_dat[3];	/* SNAP header */
	u_int16_t		an_snap_type;
};

struct an_dma_alloc {
	u_int32_t		an_dma_paddr;
	caddr_t			an_dma_vaddr;
	bus_dmamap_t		an_dma_map;
	bus_dma_segment_t	an_dma_seg;
	bus_size_t		an_dma_size;
	int			an_dma_nseg;
};

#define AN_TX_RING_CNT		4
#define AN_INC(x, y)		(x) = (x + 1) % y

struct an_tx_ring_data {
	u_int16_t		an_tx_fids[AN_TX_RING_CNT];
	u_int16_t		an_tx_ring[AN_TX_RING_CNT];
	int			an_tx_prod;
	int			an_tx_cons;
	int			an_tx_empty;
};

struct an_softc	{
	struct ifnet		*an_ifp;

	int	port_rid;	/* resource id for port range */
	struct resource* port_res; /* resource for port range */
	int     mem_rid;	/* resource id for memory range */
        int     mem_used;	/* nonzero if memory used */
	struct resource* mem_res; /* resource for memory range */
	int     mem_aux_rid;	/* resource id for memory range */
        int     mem_aux_used;	/* nonzero if memory used */
	struct resource* mem_aux_res; /* resource for memory range */
	int	irq_rid;	/* resource id for irq */
	void*	irq_handle;	/* handle for irq handler */
	struct resource* irq_res; /* resource for irq */

	bus_space_handle_t	an_mem_aux_bhandle;
	bus_space_tag_t		an_mem_aux_btag;
	bus_dma_tag_t		an_dtag;
	struct an_ltv_genconfig	an_config;
	struct an_ltv_caps	an_caps;
	struct an_ltv_ssidlist_new	an_ssidlist;
	struct an_ltv_aplist	an_aplist;
        struct an_ltv_key	an_temp_keys[4];
	int			an_tx_rate;
	int			an_rxmode;
	int			an_gone;
	int			an_if_flags;
	u_int8_t		an_txbuf[1536];
	struct an_tx_ring_data	an_rdata;
	struct an_ltv_stats	an_stats;
	struct an_ltv_status	an_status;
	u_int8_t		an_associated;
#ifdef ANCACHE
	int			an_sigitems;
	struct an_sigcache	an_sigcache[MAXANCACHE];
	int			an_nextitem;
	int			an_have_rssimap;
	struct an_ltv_rssi_map	an_rssimap;
#endif
	struct callout		an_stat_ch;
	struct mtx		an_mtx;
	device_t		an_dev;
	struct ifmedia		an_ifmedia;
	int		        an_monitor;
	int		        an_was_monitor;
	int			an_timer;
	u_char			buf_802_11[MCLBYTES];
	struct an_req		areq;
	unsigned short*		an_flash_buffer;
	int			mpi350;
	struct an_dma_alloc	an_rid_buffer;
	struct an_dma_alloc	an_rx_buffer[AN_MAX_RX_DESC];
	struct an_dma_alloc	an_tx_buffer[AN_MAX_TX_DESC];
};

#define AN_LOCK(_sc)		mtx_lock(&(_sc)->an_mtx)
#define AN_UNLOCK(_sc)		mtx_unlock(&(_sc)->an_mtx)
#define AN_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->an_mtx, MA_OWNED)

void	an_release_resources	(device_t);
int	an_alloc_port		(device_t, int, int);
int	an_alloc_memory		(device_t, int, int);
int	an_alloc_aux_memory	(device_t, int, int);
int	an_alloc_irq		(device_t, int, int);
int	an_pci_probe	(device_t);
int	an_probe	(device_t);
int	an_shutdown	(device_t);
void	an_resume	(device_t);
int	an_attach		(struct an_softc *, int);
int	an_detach	(device_t);
void    an_stop		(struct an_softc *);

driver_intr_t	an_intr;

#define AN_802_3_OFFSET		0x2E
#define AN_802_11_OFFSET	0x44
#define AN_802_11_OFFSET_RAW	0x3C

#define AN_STAT_BADCRC		0x0001
#define AN_STAT_UNDECRYPTABLE	0x0002
#define AN_STAT_ERRSTAT		0x0003
#define AN_STAT_MAC_PORT	0x0700
#define AN_STAT_1042		0x2000	/* RFC1042 encoded */
#define AN_STAT_TUNNEL		0x4000	/* Bridge-tunnel encoded */
#define AN_STAT_WMP_MSG		0x6000	/* WaveLAN-II management protocol */
#define AN_RXSTAT_MSG_TYPE	0xE000

#define AN_ENC_TX_802_3		0x00
#define AN_ENC_TX_802_11	0x11
#define AN_ENC_TX_E_II		0x0E

#define AN_ENC_TX_1042		0x00
#define AN_ENC_TX_TUNNEL	0xF8

#define AN_TXCNTL_MACPORT	0x00FF
#define AN_TXCNTL_STRUCTTYPE	0xFF00

/*
 * SNAP (sub-network access protocol) constants for transmission
 * of IP datagrams over IEEE 802 networks, taken from RFC1042.
 * We need these for the LLC/SNAP header fields in the TX/RX frame
 * structure.
 */
#define AN_SNAP_K1		0xaa	/* assigned global SAP for SNAP */
#define AN_SNAP_K2		0x00
#define AN_SNAP_CONTROL		0x03	/* unnumbered information format */
#define AN_SNAP_WORD0		(AN_SNAP_K1 | (AN_SNAP_K1 << 8))
#define AN_SNAP_WORD1		(AN_SNAP_K2 | (AN_SNAP_CONTROL << 8))
#define AN_SNAPHDR_LEN		0x6

repo_name: veiledmerc/mira

license: mit


code:
/*
 * extensions to ioctl_meteor.h for the bt848 cards
 *
 * $FreeBSD: release/9.0.0/sys/dev/bktr/ioctl_bt848.h 205781 2010-03-28 00:10:09Z gibbs $
 */

#ifndef  _DEV_BKTR_IOCTL_BT848_H_
#define  _DEV_BKTR_IOCTL_BT848_H_

/*
 * frequency sets
 */
#define CHNLSET_NABCST		1
#define CHNLSET_CABLEIRC	2
#define CHNLSET_CABLEHRC	3
#define CHNLSET_WEUROPE		4
#define CHNLSET_JPNBCST         5
#define CHNLSET_JPNCABLE        6
#define CHNLSET_XUSSR           7
#define CHNLSET_AUSTRALIA       8
#define CHNLSET_FRANCE          9
#define CHNLSET_MIN	        CHNLSET_NABCST
#define CHNLSET_MAX	        CHNLSET_FRANCE

/*
 * constants for various tuner registers
 */
#define BT848_HUEMIN		(-90)
#define BT848_HUEMAX		90
#define BT848_HUECENTER		0
#define BT848_HUERANGE		179.3
#define BT848_HUEREGMIN		(-128)
#define BT848_HUEREGMAX		127
#define BT848_HUESTEPS		256

#define BT848_BRIGHTMIN		(-50)
#define BT848_BRIGHTMAX		50
#define BT848_BRIGHTCENTER	0
#define BT848_BRIGHTRANGE	99.6
#define BT848_BRIGHTREGMIN	(-128)
#define BT848_BRIGHTREGMAX	127
#define BT848_BRIGHTSTEPS	256

#define BT848_CONTRASTMIN	0
#define BT848_CONTRASTMAX	237
#define BT848_CONTRASTCENTER	100
#define BT848_CONTRASTRANGE	236.57
#define BT848_CONTRASTREGMIN	0
#define BT848_CONTRASTREGMAX	511
#define BT848_CONTRASTSTEPS	512

#define BT848_CHROMAMIN		0
#define BT848_CHROMAMAX		284
#define BT848_CHROMACENTER	100
#define BT848_CHROMARANGE	283.89
#define BT848_CHROMAREGMIN	0
#define BT848_CHROMAREGMAX	511
#define BT848_CHROMASTEPS	512

#define BT848_SATUMIN		0
#define BT848_SATUMAX		202
#define BT848_SATUCENTER	100
#define BT848_SATURANGE		201.18
#define BT848_SATUREGMIN	0
#define BT848_SATUREGMAX	511
#define BT848_SATUSTEPS		512

#define BT848_SATVMIN		0
#define BT848_SATVMAX		284
#define BT848_SATVCENTER	100
#define BT848_SATVRANGE		283.89
#define BT848_SATVREGMIN	0
#define BT848_SATVREGMAX	511
#define BT848_SATVSTEPS		512

/*
 * audio stuff
 */
#define AUDIO_TUNER		0x00	/* command for the audio routine */
#define AUDIO_EXTERN		0x01	/* don't confuse them with bit */
#define AUDIO_INTERN		0x02	/* settings */
#define AUDIO_MUTE		0x80
#define AUDIO_UNMUTE		0x81

/*
 * EEProm stuff
 */
struct eeProm {
	short		offset;
	short		count;
	unsigned char	bytes[ 256 ];
};

/*
 * XXX: this is a hack, should be in ioctl_meteor.h
 * here to avoid touching that file for now...
 */
#define	TVTUNER_SETCHNL    _IOW('x', 32, unsigned int)	/* set channel */
#define	TVTUNER_GETCHNL    _IOR('x', 32, unsigned int)	/* get channel */
#define	TVTUNER_SETTYPE    _IOW('x', 33, unsigned int)	/* set tuner type */
#define	TVTUNER_GETTYPE    _IOR('x', 33, unsigned int)	/* get tuner type */
#define	TVTUNER_GETSTATUS  _IOR('x', 34, unsigned int)	/* get tuner status */
#define	TVTUNER_SETFREQ    _IOW('x', 35, unsigned int)	/* set frequency */
#define	TVTUNER_GETFREQ    _IOR('x', 36, unsigned int)	/* get frequency */

#define BT848_SHUE	_IOW('x', 37, int)		/* set hue */
#define BT848_GHUE	_IOR('x', 37, int)		/* get hue */
#define	BT848_SBRIG	_IOW('x', 38, int)		/* set brightness */
#define BT848_GBRIG	_IOR('x', 38, int)		/* get brightness */
#define	BT848_SCSAT	_IOW('x', 39, int)		/* set chroma sat */
#define BT848_GCSAT	_IOR('x', 39, int)		/* get UV saturation */
#define	BT848_SCONT	_IOW('x', 40, int)		/* set contrast */
#define	BT848_GCONT	_IOR('x', 40, int)		/* get contrast */
#define	BT848_SVSAT	_IOW('x', 41, int)		/* set chroma V sat */
#define BT848_GVSAT	_IOR('x', 41, int)		/* get V saturation */
#define	BT848_SUSAT	_IOW('x', 42, int)		/* set chroma U sat */
#define BT848_GUSAT	_IOR('x', 42, int)		/* get U saturation */

#define	BT848_SCBARS	_IOR('x', 43, int)		/* set colorbar */
#define	BT848_CCBARS	_IOR('x', 44, int)		/* clear colorbar */

#define	BT848_SAUDIO	_IOW('x', 46, int)		/* set audio channel */
#define BT848_GAUDIO	_IOR('x', 47, int)		/* get audio channel */
#define	BT848_SBTSC	_IOW('x', 48, int)		/* set audio channel */

#define	BT848_GSTATUS	_IOR('x', 49, unsigned int)	/* reap status */

#define	BT848_WEEPROM	_IOWR('x', 50, struct eeProm)	/* write to EEProm */
#define	BT848_REEPROM	_IOWR('x', 51, struct eeProm)	/* read from EEProm */

#define	BT848_SIGNATURE	_IOWR('x', 52, struct eeProm)	/* read card sig */

#define	TVTUNER_SETAFC	_IOW('x', 53, int)		/* turn AFC on/off */
#define TVTUNER_GETAFC	_IOR('x', 54, int)		/* query AFC on/off */
#define BT848_SLNOTCH	_IOW('x', 55, int)		/* set luma notch */
#define BT848_GLNOTCH	_IOR('x', 56, int)		/* get luma notch */

/* Read/Write the BT848's I2C bus directly
 * b7-b0:    data (read/write)
 * b15-b8:   internal peripheral register (write)
 * b23-b16:  i2c addr (write)
 * b31-b24:  1 = write, 0 = read
 */
#define BT848_I2CWR     _IOWR('x', 57, unsigned long)    /* i2c read-write */

struct bktr_msp_control {
	unsigned char function;
	unsigned int  address;
	unsigned int  data;
};

#define BT848_MSP_RESET _IO('x', 76)				/* MSP chip reset */
#define BT848_MSP_READ  _IOWR('x', 77, struct bktr_msp_control)	/* MSP chip read */
#define BT848_MSP_WRITE _IOWR('x', 78, struct bktr_msp_control)	/* MSP chip write */

/* Support for radio tuner */
#define RADIO_SETMODE	 _IOW('x', 58, unsigned int)  /* set radio modes */
#define RADIO_GETMODE	 _IOR('x', 58, unsigned char)  /* get radio modes */
#define   RADIO_AFC	 0x01		/* These modes will probably not */
#define   RADIO_MONO	 0x02		/*  work on the FRxxxx. It does	 */
#define   RADIO_MUTE	 0x08		/*  work on the FMxxxx.	*/
#define RADIO_SETFREQ    _IOW('x', 59, unsigned int)  /* set frequency   */
#define RADIO_GETFREQ    _IOR('x', 59, unsigned int)  /* set frequency   */
 /*        Argument is frequency*100MHz  */

/*
 * XXX: more bad magic,
 *      we need to fix the METEORGINPUT to return something public
 *      duplicate them here for now...
 */
#define	METEOR_DEV0		0x00001000
#define	METEOR_DEV1		0x00002000
#define	METEOR_DEV2		0x00004000
#define	METEOR_DEV3		0x00008000
#define	METEOR_DEV_SVIDEO	0x00006000
/*
 * right now I don't know were to put these, but as they are suppose to be
 * a part of a common video capture interface, these should be relocated to
 * another place.  Probably most of the METEOR_xxx defines need to be
 * renamed and moved to a common header
 */

typedef enum { METEOR_PIXTYPE_RGB, METEOR_PIXTYPE_YUV,
	       METEOR_PIXTYPE_YUV_PACKED,
	       METEOR_PIXTYPE_YUV_12 } METEOR_PIXTYPE;

struct meteor_pixfmt {
	unsigned int   index;         /* Index in supported pixfmt list     */
	METEOR_PIXTYPE type;          /* What's the board gonna feed us     */
	unsigned int   Bpp;           /* Bytes per pixel                    */
	unsigned long  masks[3];      /* R,G,B or Y,U,V masks, respectively */
	unsigned       swap_bytes :1; /* Bytes  swapped within shorts       */
	unsigned       swap_shorts:1; /* Shorts swapped within longs        */
};

struct bktr_clip {
    int          x_min;
    int          x_max;
    int          y_min;
    int          y_max;
};

#define BT848_MAX_CLIP_NODE 100
struct _bktr_clip {
    struct bktr_clip x[BT848_MAX_CLIP_NODE];
};

/*
 * I'm using METEOR_xxx just because that will be common to other interface
 * and less of a surprise
 */
#define METEORSACTPIXFMT	_IOW('x', 64, int )
#define METEORGACTPIXFMT	_IOR('x', 64, int )
#define METEORGSUPPIXFMT	_IOWR('x', 65, struct meteor_pixfmt)

/* set clip list */
#define BT848SCLIP     _IOW('x', 66, struct _bktr_clip )
#define BT848GCLIP     _IOR('x', 66, struct _bktr_clip )

/* set input format */
#define BT848SFMT		_IOW('x', 67, unsigned long )
#define BT848GFMT		_IOR('x', 67, unsigned long )

/* set clear-buffer-on-start */
#define BT848SCBUF	_IOW('x', 68, int)
#define BT848GCBUF	_IOR('x', 68, int)

/* set capture area */
/* The capture area is the area of the video image which is grabbed */
/* Usually the capture area is 640x480 (768x576 PAL) pixels */
/* This area is then scaled to the dimensions the user requires */
/* using the METEORGEO ioctl */
/* However, the capture area could be 400x300 pixels from the top right */
/* corner of the video image */
struct bktr_capture_area {
   int      x_offset;
   int      y_offset;
   int      x_size;
   int      y_size;
};
#define BT848_SCAPAREA   _IOW('x', 69, struct bktr_capture_area)
#define BT848_GCAPAREA   _IOR('x', 69, struct bktr_capture_area)

/* Get channel Set */
#define BT848_MAX_CHNLSET_NAME_LEN 16
struct bktr_chnlset {
       short   index;
       short   max_channel;
       char    name[BT848_MAX_CHNLSET_NAME_LEN];
};
#define	TVTUNER_GETCHNLSET _IOWR('x', 70, struct bktr_chnlset)

/* Infra Red Remote Control */
struct bktr_remote {
       unsigned char data[3];
};
#define	REMOTE_GETKEY      _IOR('x', 71, struct bktr_remote)/*read the remote */
                                                            /*control receiver*/
                                                            /*returns raw data*/

/*
 * Direct access to GPIO pins. You must add BKTR_GPIO_ACCESS to your kernel
 * configuration file to use these
 */
#define BT848_GPIO_SET_EN      _IOW('x', 72, int)      /* set gpio_out_en */
#define BT848_GPIO_GET_EN      _IOR('x', 73, int)      /* get gpio_out_en */
#define BT848_GPIO_SET_DATA    _IOW('x', 74, int)      /* set gpio_data */
#define BT848_GPIO_GET_DATA    _IOR('x', 75, int)      /* get gpio_data */

/*  XXX - Copied from /sys/pci/brktree_reg.h  */
#define BT848_IFORM_FORMAT              (0x7<<0)
# define BT848_IFORM_F_RSVD             (0x7)
# define BT848_IFORM_F_SECAM            (0x6)
# define BT848_IFORM_F_PALN             (0x5)
# define BT848_IFORM_F_PALM             (0x4)
# define BT848_IFORM_F_PALBDGHI         (0x3)
# define BT848_IFORM_F_NTSCJ            (0x2)
# define BT848_IFORM_F_NTSCM            (0x1)
# define BT848_IFORM_F_AUTO             (0x0)

#endif	/* _DEV_BKTR_IOCTL_BT848_H_ */


code:
/*-
 * Copyright (c) 1995 Mark Tinguely and Jim Lowe
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Mark Tinguely and Jim Lowe
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/dev/bktr/ioctl_meteor.h 205781 2010-03-28 00:10:09Z gibbs $
 */
/*
 *	ioctl constants for Matrox Meteor Capture card.
 */

#ifndef	_DEV_BKTR_IOCTL_METEOR_H_
#define	_DEV_BKTR_IOCTL_METEOR_H_

#ifndef _KERNEL
#include <sys/types.h>
#endif
#include <sys/ioccom.h>

struct meteor_capframe {
	short	command;	/* see below for valid METEORCAPFRM commands */
	short	lowat;		/* start transfer if < this number */
	short	hiwat;		/* stop transfer if > this number */
} ;

/* structure for METEOR[GS]ETGEO - get/set geometry  */
struct meteor_geomet {
	unsigned short		rows;
	unsigned short		columns;
	unsigned short		frames;
	unsigned long		oformat;
} ;

/* structure for METEORGCOUNT-get count of frames, fifo errors and dma errors */
struct meteor_counts {
	unsigned long fifo_errors;	/* count of fifo errors since open */
	unsigned long dma_errors;	/* count of dma errors since open */
	unsigned long frames_captured;	/* count of frames captured since open */
	unsigned long even_fields_captured; /* count of even fields captured */
	unsigned long odd_fields_captured; /* count of odd fields captured */
} ;

/* structure for getting and setting direct transfers to vram */
struct meteor_video {
	unsigned long	addr;		/* Address of location to dma to */
	unsigned long	width;		/* Width of memory area */
	unsigned long	banksize;	/* Size of Vram bank */
	unsigned long	ramsize;	/* Size of Vram */
};

#define METEORCAPTUR _IOW('x', 1, int)			 /* capture a frame */
#define METEORCAPFRM _IOW('x', 2, struct meteor_capframe)  /* sync capture */
#define METEORSETGEO _IOW('x', 3, struct meteor_geomet)  /* set geometry */
#define METEORGETGEO _IOR('x', 4, struct meteor_geomet)  /* get geometry */
#define METEORSTATUS _IOR('x', 5, unsigned short)	/* get status */
#define METEORSHUE   _IOW('x', 6, signed char)		/* set hue */
#define METEORGHUE   _IOR('x', 6, signed char)		/* get hue */
#define METEORSFMT   _IOW('x', 7, unsigned long)	/* set format */
#define METEORGFMT   _IOR('x', 7, unsigned long)	/* get format */
#define METEORSINPUT _IOW('x', 8, unsigned long)	/* set input dev */
#define METEORGINPUT _IOR('x', 8, unsigned long)	/* get input dev */
#define	METEORSCHCV  _IOW('x', 9, unsigned char)	/* set uv gain */
#define	METEORGCHCV  _IOR('x', 9, unsigned char)	/* get uv gain */
#define	METEORSCOUNT _IOW('x',10, struct meteor_counts)
#define	METEORGCOUNT _IOR('x',10, struct meteor_counts)
#define METEORSFPS   _IOW('x',11, unsigned short)	/* set fps */
#define METEORGFPS   _IOR('x',11, unsigned short)	/* get fps */
#define METEORSSIGNAL _IOW('x', 12, unsigned int)	/* set signal */
#define METEORGSIGNAL _IOR('x', 12, unsigned int)	/* get signal */
#define	METEORSVIDEO _IOW('x', 13, struct meteor_video)	/* set video */
#define	METEORGVIDEO _IOR('x', 13, struct meteor_video)	/* get video */
#define	METEORSBRIG  _IOW('x', 14, unsigned char)	/* set brightness */
#define METEORGBRIG  _IOR('x', 14, unsigned char)	/* get brightness */
#define	METEORSCSAT  _IOW('x', 15, unsigned char)	/* set chroma sat */
#define METEORGCSAT  _IOR('x', 15, unsigned char)	/* get uv saturation */
#define	METEORSCONT  _IOW('x', 16, unsigned char)	/* set contrast */
#define	METEORGCONT  _IOR('x', 16, unsigned char)	/* get contrast */
#define METEORSBT254 _IOW('x', 17, unsigned short)	/* set Bt254 reg */
#define METEORGBT254 _IOR('x', 17, unsigned short)	/* get Bt254 reg */
#define METEORSHWS   _IOW('x', 18, unsigned char)	/* set hor start reg */
#define METEORGHWS   _IOR('x', 18, unsigned char)	/* get hor start reg */
#define METEORSVWS   _IOW('x', 19, unsigned char)	/* set vert start reg */
#define METEORGVWS   _IOR('x', 19, unsigned char)	/* get vert start reg */
#define	METEORSTS    _IOW('x', 20, unsigned char)	/* set time stamp */
#define	METEORGTS    _IOR('x', 20, unsigned char)	/* get time stamp */

#define	METEOR_STATUS_ID_MASK	0xf000	/* ID of 7196 */
#define	METEOR_STATUS_DIR	0x0800	/* Direction of Expansion port YUV */
#define	METEOR_STATUS_OEF	0x0200	/* Field detected: Even/Odd */
#define	METEOR_STATUS_SVP	0x0100	/* State of VRAM Port:inactive/active */
#define	METEOR_STATUS_STTC	0x0080	/* Time Constant: TV/VCR */
#define	METEOR_STATUS_HCLK	0x0040	/* Horiz PLL: locked/unlocked */
#define	METEOR_STATUS_FIDT	0x0020	/* Field detect: 50/60hz */
#define	METEOR_STATUS_ALTD	0x0002	/* Line alt: no line alt/line alt */
#define METEOR_STATUS_CODE	0x0001	/* Colour info: no colour/colour */

				/* METEORCAPTUR capture options */
#define METEOR_CAP_SINGLE	0x0001	/* capture one frame */
#define METEOR_CAP_CONTINOUS	0x0002	/* continuously capture */
#define METEOR_CAP_STOP_CONT	0x0004	/* stop the continuous capture */

				/* METEORCAPFRM capture commands */
#define METEOR_CAP_N_FRAMES	0x0001	/* capture N frames */
#define METEOR_CAP_STOP_FRAMES	0x0002	/* stop capture N frames */
#define	METEOR_HALT_N_FRAMES	0x0003	/* halt of capture N frames */
#define METEOR_CONT_N_FRAMES	0x0004	/* continue after above halt */

				/* valid video input formats:  */
#define METEOR_FMT_NTSC		0x00100	/* NTSC --  initialized default */
#define METEOR_FMT_PAL		0x00200	/* PAL */
#define METEOR_FMT_SECAM	0x00400	/* SECAM */
#define METEOR_FMT_AUTOMODE	0x00800 /* auto-mode */
#define METEOR_INPUT_DEV0	0x01000	/* camera input 0 -- default */
#define METEOR_INPUT_DEV_RCA	METEOR_INPUT_DEV0
#define METEOR_INPUT_DEV1	0x02000	/* camera input 1 */
#define METEOR_INPUT_DEV2	0x04000	/* camera input 2 */
#define METEOR_INPUT_DEV3	0x08000	/* camera input 3 */
#define METEOR_INPUT_DEV_RGB	0x0a000	/* for rgb version of meteor */
#define METEOR_INPUT_DEV_SVIDEO	0x06000 /* S-video input port */

				/* valid video output formats:  */
#define METEOR_GEO_RGB16	0x0010000 /* packed -- initialized default */
#define METEOR_GEO_RGB24	0x0020000 /* RBG 24 bits packed */
					  /* internally stored in 32 bits */
#define METEOR_GEO_YUV_PACKED	0x0040000 /* 4-2-2 YUV 16 bits packed */
#define METEOR_GEO_YUV_PLANAR	0x0080000 /* 4-2-2 YUV 16 bits planer */
#define METEOR_GEO_YUV_PLANER	METEOR_GEO_YUV_PLANAR
#define METEOR_GEO_UNSIGNED	0x0400000 /* unsigned uv outputs */
#define METEOR_GEO_EVEN_ONLY	0x1000000 /* set for even only field capture */
#define METEOR_GEO_ODD_ONLY	0x2000000 /* set for odd only field capture */
#define METEOR_GEO_FIELD_MASK	0x3000000
#define METEOR_GEO_YUV_422	0x4000000 /* 4-2-2 YUV in Y-U-V combined */
#define METEOR_GEO_OUTPUT_MASK	0x40f0000
#define METEOR_GEO_YUV_12	0x10000000	/* YUV 12 format */
#define METEOR_GEO_YUV_9	0x40000000	/* YUV 9 format */

#define	METEOR_FIELD_MODE	0x80000000	/* Field cap or Frame cap */

#define	METEOR_SIG_MODE_MASK	0xffff0000
#define	METEOR_SIG_FRAME	0x00000000	/* signal every frame */
#define	METEOR_SIG_FIELD	0x00010000	/* signal every field */

	/* following structure is used to coordinate the synchronous */

struct meteor_mem {
		/* kernel write only  */
	int	frame_size;	 /* row*columns*depth */
	unsigned num_bufs;	 /* number of frames in buffer (1-32) */
		/* user and kernel change these */
	int	lowat;		 /* kernel starts capture if < this number */
	int	hiwat;		 /* kernel stops capture if > this number.
				    hiwat <= numbufs */
	unsigned active;	 /* bit mask of active frame buffers
				    kernel sets, user clears */
	int	num_active_bufs; /* count of active frame buffer
				    kernel increments, user decrements */

		/* reference to mmapped data */
	caddr_t	buf;		 /* The real space (virtual addr) */
} ;

#endif /* !_DEV_BKTR_IOCTL_METEOR_H_ */


code:
/*-
 * Copyright (c) 2001 Michael Smith
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$FreeBSD: release/9.0.0/sys/dev/ciss/cissio.h 180454 2008-07-11 21:20:51Z scottl $
 */

/*
 * Driver ioctl interface.
 *
 * Note that this interface is API-compatible with the Linux implementation
 * except as noted, and thus this header bears a striking resemblance to
 * the Linux driver's cciss_ioctl.h.
 *
 */

#include <sys/ioccom.h>

#pragma pack(1)

typedef struct
{
    u_int8_t	bus;
    u_int8_t	dev_fn;
    u_int32_t	board_id;
} cciss_pci_info_struct;

typedef struct
{
    u_int32_t	delay;
    u_int32_t	count;
} cciss_coalint_struct;

typedef char		NodeName_type[16];
typedef u_int32_t	Heartbeat_type;

#define CISS_PARSCSIU2	0x0001
#define CISS_PARCSCIU3	0x0002
#define CISS_FIBRE1G	0x0100
#define CISS_FIBRE2G	0x0200
typedef u_int32_t	BusTypes_type;

typedef char		FirmwareVer_type[4];
typedef u_int32_t	DriverVer_type;

/* passthrough command definitions */
#define SENSEINFOBYTES          32
#define CISS_MAX_LUN		16
#define LEVEL2LUN		1
#define LEVEL3LUN		0

/* command status value */
#define CMD_SUCCESS		0x0000
#define CMD_TARGET_STATUS	0x0001
#define CMD_DATA_UNDERRUN	0x0002
#define CMD_DATA_OVERRUN	0x0003
#define CMD_INVALID		0x0004
#define CMD_PROTOCOL_ERR	0x0005
#define CMD_HARDWARE_ERR	0x0006
#define CMD_CONNECTION_LOST	0x0007
#define CMD_ABORTED		0x0008
#define CMD_ABORT_FAILED	0x0009
#define CMD_UNSOLICITED_ABORT	0x000A
#define CMD_TIMEOUT		0x000B
#define CMD_UNABORTABLE		0x000C

/* transfer direction */
#define XFER_NONE		0x00
#define XFER_WRITE		0x01
#define XFER_READ		0x02
#define XFER_RSVD		0x03

/* task attribute */
#define ATTR_UNTAGGED		0x00
#define ATTR_SIMPLE		0x04
#define ATTR_HEADOFQUEUE	0x05
#define ATTR_ORDERED		0x06
#define ATTR_ACA		0x07

/* CDB type */
#define TYPE_CMD		0x00
#define TYPE_MSG		0x01

/* command list structure */
typedef union {
    struct {
	u_int8_t	Dev;
	u_int8_t	Bus:6;
	u_int8_t	Mode:2;
    } __packed PeripDev;
    struct {
	u_int8_t	DevLSB;
	u_int8_t	DevMSB:6;
	u_int8_t	Mode:2;
    } __packed LogDev;
    struct {
	u_int8_t	Dev:5;
	u_int8_t	Bus:3;
	u_int8_t	Targ:6;
	u_int8_t	Mode:2;
    } __packed LogUnit;
} SCSI3Addr_struct;

typedef struct {
    u_int32_t		TargetId:24;
    u_int32_t		Bus:6;
    u_int32_t		Mode:2;
    SCSI3Addr_struct	Target[2];
} __packed PhysDevAddr_struct;

typedef struct {
    u_int32_t		VolId:30;
    u_int32_t		Mode:2;
    u_int8_t		reserved[4];
} __packed LogDevAddr_struct;

typedef union {
    u_int8_t		LunAddrBytes[8];
    SCSI3Addr_struct	SCSI3Lun[4];
    PhysDevAddr_struct	PhysDev;
    LogDevAddr_struct	LogDev;
} __packed LUNAddr_struct;

typedef struct {
    u_int8_t	CDBLen;
    struct {
	u_int8_t	Type:3;
	u_int8_t	Attribute:3;
	u_int8_t	Direction:2;
    } __packed Type;
    u_int16_t	Timeout;
    u_int8_t	CDB[16];
} __packed RequestBlock_struct;

typedef union {
    struct {
	u_int8_t	Reserved[3];
	u_int8_t	Type;
	u_int32_t	ErrorInfo;
    } __packed Common_Info;
    struct {
	u_int8_t	Reserved[2];
	u_int8_t	offense_size;
	u_int8_t	offense_num;
	u_int32_t	offense_value;
    } __packed Invalid_Cmd;
} __packed MoreErrInfo_struct;

typedef struct {
    u_int8_t		ScsiStatus;
    u_int8_t		SenseLen;
    u_int16_t		CommandStatus;
    u_int32_t		ResidualCnt;
    MoreErrInfo_struct	MoreErrInfo;
    u_int8_t		SenseInfo[SENSEINFOBYTES];
} __packed ErrorInfo_struct;

typedef struct {
    LUNAddr_struct	LUN_info;	/* 8 */
    RequestBlock_struct	Request;	/* 20 */
    ErrorInfo_struct	error_info;	/* 48 */
    u_int16_t		buf_size;	/* 2 */
    u_int8_t		*buf;		/* 4 */
} __packed IOCTL_Command_struct;

#ifdef __amd64__
typedef struct {
    LUNAddr_struct	LUN_info;	/* 8 */
    RequestBlock_struct	Request;	/* 20 */
    ErrorInfo_struct	error_info;	/* 48 */
    u_int16_t		buf_size;	/* 2 */
    u_int32_t		buf;		/* 4 */
} __packed IOCTL_Command_struct32;
#endif

/************************************************************************
 * Command queue statistics
 */

#define CISSQ_FREE	0
#define CISSQ_NOTIFY	1
#define CISSQ_COUNT	2

struct ciss_qstat {
    uint32_t		q_length;
    uint32_t		q_max;
};

union ciss_statrequest {
    uint32_t		cs_item;
    struct ciss_qstat	cs_qstat;
};

/*
 * Note that we'd normally pass the struct in directly, but
 * this code is trying to be compatible with other drivers.
 */
#define CCISS_GETPCIINFO	_IOR ('C', 200, cciss_pci_info_struct)
#define CCISS_GETINTINFO	_IOR ('C', 201, cciss_coalint_struct)
#define CCISS_SETINTINFO	_IOW ('C', 202, cciss_coalint_struct)
#define CCISS_GETNODENAME	_IOR ('C', 203, NodeName_type)
#define CCISS_SETNODENAME	_IOW ('C', 204, NodeName_type)
#define CCISS_GETHEARTBEAT	_IOR ('C', 205, Heartbeat_type)
#define CCISS_GETBUSTYPES	_IOR ('C', 206, BusTypes_type)
#define CCISS_GETFIRMVER	_IOR ('C', 207, FirmwareVer_type)
#define CCISS_GETDRIVERVER	_IOR ('C', 208, DriverVer_type)
#define CCISS_REVALIDVOLS	_IO  ('C', 209)
#define CCISS_PASSTHRU		_IOWR ('C', 210, IOCTL_Command_struct)
#ifdef __amd64
#define CCISS_PASSTHRU32	_IOWR ('C', 210, IOCTL_Command_struct32)
#endif
#define CCISS_GETQSTATS		_IOWR ('C', 211, union ciss_statrequest)

#pragma pack()


code:
/*-
 * Copyright (c) 2001 Michael Smith
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$FreeBSD: release/9.0.0/sys/dev/ciss/cissreg.h 197263 2009-09-16 23:27:14Z scottl $
 */

/*
 * Structure and I/O definitions for the Command Interface for SCSI-3 Support.
 *
 * Data in command CDBs are in big-endian format.  All other data is little-endian.
 * This header only supports little-endian hosts at this time.
 */

union ciss_device_address
{
    struct 				/* MODE_PERIPHERAL and MODE_MASK_PERIPHERAL */
    {
	u_int32_t	target:24;	/* SCSI target */
	u_int32_t	bus:6;		/* SCSI bus */
	u_int32_t	mode:2;		/* CISS_HDR_ADDRESS_MODE_* */
	u_int32_t	extra_address;	/* SCSI-3 level-2 and level-3 address bytes */
    } physical;
    struct 				/* MODE_LOGICAL */
    {
	u_int32_t	lun:30;		/* logical device ID */
	u_int32_t	mode:2;		/* CISS_HDR_ADDRESS_MODE_LOGICAL */
	u_int32_t	:32;		/* reserved */
    } logical;
    struct
    {
	u_int32_t	:30;
	u_int32_t	mode:2;
	u_int32_t	:32;
    } mode;
};
#define CISS_HDR_ADDRESS_MODE_PERIPHERAL	0x0
#define CISS_HDR_ADDRESS_MODE_LOGICAL		0x1
#define CISS_HDR_ADDRESS_MODE_MASK_PERIPHERAL	0x3

#define CISS_EXTRA_MODE2(extra)		((extra & 0xc0000000) >> 30)
#define CISS_EXTRA_BUS2(extra)		((extra & 0x3f000000) >> 24)
#define CISS_EXTRA_TARGET2(extra)	((extra & 0x00ff0000) >> 16)
#define CISS_EXTRA_MODE3(extra)		((extra & 0x0000c000) >> 14)
#define CISS_EXTRA_BUS3(extra)		((extra & 0x00003f00) >> 8)
#define CISS_EXTRA_TARGET3(extra)	((extra & 0x000000ff))

struct ciss_header
{
    u_int8_t	:8;			/* reserved */
    u_int8_t	sg_in_list;		/* SG's in the command structure */
    u_int16_t	sg_total;		/* total count of SGs for this command */
    u_int32_t	host_tag;		/* host identifier, bits 0&1 must be clear */
#define CISS_HDR_HOST_TAG_ERROR	(1<<1)
    u_int32_t	host_tag_zeroes;	/* tag is 64 bits, but interface only supports 32 */
    union ciss_device_address address;
} __packed;

struct ciss_cdb
{
    u_int8_t	cdb_length;		/* valid CDB bytes */
    u_int8_t	type:3;
#define CISS_CDB_TYPE_COMMAND			0
#define CISS_CDB_TYPE_MESSAGE			1
    u_int8_t	attribute:3;
#define CISS_CDB_ATTRIBUTE_UNTAGGED		0
#define CISS_CDB_ATTRIBUTE_SIMPLE		4
#define CISS_CDB_ATTRIBUTE_HEAD_OF_QUEUE	5
#define CISS_CDB_ATTRIBUTE_ORDERED		6
#define CISS_CDB_ATTRIBUTE_AUTO_CONTINGENT	7
    u_int8_t	direction:2;
#define CISS_CDB_DIRECTION_NONE			0
#define CISS_CDB_DIRECTION_WRITE		1
#define CISS_CDB_DIRECTION_READ			2
    u_int16_t	timeout;		/* seconds */
#define CISS_CDB_BUFFER_SIZE	16
    u_int8_t	cdb[CISS_CDB_BUFFER_SIZE];
} __packed;

struct ciss_error_info_pointer
{
    u_int64_t	error_info_address;	/* points to ciss_error_info structure */
    u_int32_t	error_info_length;
} __packed;

struct ciss_error_info
{
    u_int8_t	scsi_status;
#define CISS_SCSI_STATUS_GOOD			0x00	/* these are scsi-standard values */
#define CISS_SCSI_STATUS_CHECK_CONDITION	0x02
#define CISS_SCSI_STATUS_CONDITION_MET		0x04
#define CISS_SCSI_STATUS_BUSY			0x08
#define CISS_SCSI_STATUS_INDETERMINATE		0x10
#define CISS_SCSI_STATUS_INDETERMINATE_CM	0x14
#define CISS_SCSI_STATUS_RESERVATION_CONFLICT	0x18
#define CISS_SCSI_STATUS_COMMAND_TERMINATED	0x22
#define CISS_SCSI_STATUS_QUEUE_FULL		0x28
#define CISS_SCSI_STATUS_ACA_ACTIVE		0x30
    u_int8_t	sense_length;
    u_int16_t	command_status;
#define CISS_CMD_STATUS_SUCCESS			0
#define CISS_CMD_STATUS_TARGET_STATUS		1
#define CISS_CMD_STATUS_DATA_UNDERRUN		2
#define CISS_CMD_STATUS_DATA_OVERRUN		3
#define CISS_CMD_STATUS_INVALID_COMMAND		4
#define CISS_CMD_STATUS_PROTOCOL_ERROR		5
#define CISS_CMD_STATUS_HARDWARE_ERROR		6
#define CISS_CMD_STATUS_CONNECTION_LOST		7
#define CISS_CMD_STATUS_ABORTED			8
#define CISS_CMD_STATUS_ABORT_FAILED		9
#define CISS_CMD_STATUS_UNSOLICITED_ABORT	10
#define CISS_CMD_STATUS_TIMEOUT			11
#define CISS_CMD_STATUS_UNABORTABLE		12
    u_int32_t	residual_count;
    union {
	struct {
	    u_int8_t	res1[3];
	    u_int8_t	type;
	    u_int32_t	error_info;
	} __packed common_info;
	struct {
	    u_int8_t	res1[2];
	    u_int8_t	offense_size;
	    u_int8_t	offense_offset;
	    u_int32_t	offense_value;
	} __packed invalid_command;
    } additional_error_info;
    u_int8_t	sense_info[0];
} __packed;

struct ciss_sg_entry
{
    u_int64_t	address;
#define CISS_SG_ADDRESS_BITBUCKET	(~(u_int64_t)0)
    u_int32_t	length;
    u_int32_t	:31;
    u_int32_t	extension:1;		/* address points to another s/g chain */
} __packed;

struct ciss_command
{
    struct ciss_header			header;
    struct ciss_cdb			cdb;
    struct ciss_error_info_pointer	error_info;
    struct ciss_sg_entry		sg[0];
} __packed;

#define CISS_OPCODE_REPORT_LOGICAL_LUNS		0xc2
#define CISS_OPCODE_REPORT_PHYSICAL_LUNS	0xc3

struct ciss_lun_report
{
    u_int32_t	list_size;		/* big-endian */
    u_int32_t	:32;
    union ciss_device_address lun[0];
} __packed;

#define	CISS_VPD_LOGICAL_DRIVE_GEOMETRY		0xc1
struct ciss_ldrive_geometry
{
    u_int8_t	periph_qualifier:3;
    u_int8_t	periph_devtype:5;
    u_int8_t	page_code;
    u_int8_t	res1;
    u_int8_t	page_length;
    u_int16_t	cylinders;		/* big-endian */
    u_int8_t	heads;
    u_int8_t	sectors;
    u_int8_t	fault_tolerance;
    u_int8_t	res2[3];
} __attribute__ ((packed));

struct ciss_report_cdb
{
    u_int8_t	opcode;
    u_int8_t	reserved[5];
    u_int32_t	length;			/* big-endian */
    u_int8_t	:8;
    u_int8_t	control;
} __packed;

/*
 * Note that it's not clear whether we have to set the detail field to
 * the tag of the command to be aborted, or the tag field in the command itself;
 * documentation conflicts on this.
 */
#define CISS_OPCODE_MESSAGE_ABORT		0x00
#define CISS_MESSAGE_ABORT_TASK			0x00
#define CISS_MESSAGE_ABORT_TASK_SET		0x01
#define CISS_MESSAGE_ABORT_CLEAR_ACA		0x02
#define CISS_MESSAGE_ABORT_CLEAR_TASK_SET	0x03

#define CISS_OPCODE_MESSAGE_RESET		0x01
#define CISS_MESSAGE_RESET_CONTROLLER		0x00
#define CISS_MESSAGE_RESET_BUS			0x01
#define CISS_MESSAGE_RESET_TARGET		0x03
#define CISS_MESSAGE_RESET_LOGICAL_UNIT		0x04

#define CISS_OPCODE_MESSAGE_SCAN		0x02
#define CISS_MESSAGE_SCAN_CONTROLLER		0x00
#define CISS_MESSAGE_SCAN_BUS			0x01
#define CISS_MESSAGE_SCAN_TARGET		0x03
#define CISS_MESSAGE_SCAN_LOGICAL_UNIT		0x04

#define CISS_OPCODE_MESSAGE_NOP			0x03

struct ciss_message_cdb
{
    u_int8_t	opcode;
    u_int8_t	type;
    u_int16_t	:16;
    u_int32_t	abort_tag;					/* XXX endianness? */
    u_int8_t	reserved[8];
} __packed;

/*
 * CISS vendor-specific commands/messages.
 *
 * Note that while messages and vendor-specific commands are
 * differentiated, they are handled in basically the same way and can
 * be considered to be basically the same thing, as long as the cdb
 * type field is set correctly.
 */
#define CISS_OPCODE_READ		0xc0
#define CISS_OPCODE_WRITE		0xc1
#define CISS_COMMAND_NOTIFY_ON_EVENT	0xd0
#define CISS_COMMAND_ABORT_NOTIFY	0xd1

struct ciss_notify_cdb
{
    u_int8_t	opcode;
    u_int8_t	command;
    u_int8_t	res1[2];
    u_int16_t	timeout;		/* seconds, little-endian */
    u_int8_t	res2;			/* reserved */
    u_int8_t	synchronous:1;		/* return immediately */
    u_int8_t	ordered:1;		/* return events in recorded order */
    u_int8_t	seek_to_oldest:1;	/* reset read counter to oldest event */
    u_int8_t	new_only:1;		/* ignore any queued events */
    u_int8_t	:4;
    u_int32_t	length;			/* must be 512, little-endian */
#define CISS_NOTIFY_DATA_SIZE	512
    u_int8_t	control;
} __packed;

#define CISS_NOTIFY_NOTIFIER		0
#define CISS_NOTIFY_NOTIFIER_STATUS		0
#define CISS_NOTIFY_NOTIFIER_PROTOCOL		1

#define CISS_NOTIFY_HOTPLUG		1
#define CISS_NOTIFY_HOTPLUG_PHYSICAL		0
#define CISS_NOTIFY_HOTPLUG_POWERSUPPLY		1
#define CISS_NOTIFY_HOTPLUG_FAN			2
#define CISS_NOTIFY_HOTPLUG_POWER		3
#define CISS_NOTIFY_HOTPLUG_REDUNDANT		4
#define CISS_NOTIFY_HOTPLUG_NONDISK		5

#define CISS_NOTIFY_HARDWARE		2
#define CISS_NOTIFY_HARDWARE_CABLES		0
#define CISS_NOTIFY_HARDWARE_MEMORY		1
#define CISS_NOTIFY_HARDWARE_FAN		2
#define CISS_NOTIFY_HARDWARE_VRM		3

#define CISS_NOTIFY_ENVIRONMENT		3
#define CISS_NOTIFY_ENVIRONMENT_TEMPERATURE	0
#define CISS_NOTIFY_ENVIRONMENT_POWERSUPPLY	1
#define CISS_NOTIFY_ENVIRONMENT_CHASSIS		2
#define CISS_NOTIFY_ENVIRONMENT_POWER		3

#define CISS_NOTIFY_PHYSICAL		4
#define CISS_NOTIFY_PHYSICAL_STATE		0

#define CISS_NOTIFY_LOGICAL		5
#define CISS_NOTIFY_LOGICAL_STATUS		0
#define CISS_NOTIFY_LOGICAL_ERROR		1
#define CISS_NOTIFY_LOGICAL_SURFACE		2

#define CISS_NOTIFY_REDUNDANT		6
#define CISS_NOTIFY_REDUNDANT_STATUS		0

#define CISS_NOTIFY_CISS		8
#define CISS_NOTIFY_CISS_REDUNDANT_CHANGE	0
#define CISS_NOTIFY_CISS_PATH_STATUS		1
#define CISS_NOTIFY_CISS_HARDWARE_ERROR		2
#define CISS_NOTIFY_CISS_LOGICAL		3

struct ciss_notify_drive
{
    u_int16_t	physical_drive_number;
    u_int8_t	configured_drive_flag;
    u_int8_t	spare_drive_flag;
    u_int8_t	big_physical_drive_number;
    u_int8_t	enclosure_bay_number;
} __packed;

struct ciss_notify_locator
{
    u_int16_t	port;
    u_int16_t	id;
    u_int16_t	box;
} __packed;

struct ciss_notify_redundant_controller
{
    u_int16_t	slot;
} __packed;

struct ciss_notify_logical_status
{
    u_int16_t	logical_drive;
    u_int8_t	previous_state;
    u_int8_t	new_state;
    u_int8_t	spare_state;
} __packed;

struct ciss_notify_rebuild_aborted
{
    u_int16_t	logical_drive;
    u_int8_t	replacement_drive;
    u_int8_t	error_drive;
    u_int8_t	big_replacement_drive;
    u_int8_t	big_error_drive;
} __packed;

struct ciss_notify_io_error
{
    u_int16_t	logical_drive;
    u_int32_t	lba;
    u_int16_t	block_count;
    u_int8_t	command;
    u_int8_t	failure_bus;
    u_int8_t	failure_drive;
    u_int64_t	big_lba;
} __packed;

struct ciss_notify_consistency_completed
{
    u_int16_t	logical_drive;
} __packed;

struct ciss_notify
{
    u_int32_t	timestamp;		/* seconds since controller power-on */
    u_int16_t	class;
    u_int16_t	subclass;
    u_int16_t	detail;
    union
    {
	struct ciss_notify_drive		drive;
	struct ciss_notify_locator		location;
	struct ciss_notify_redundant_controller	redundant_controller;
	struct ciss_notify_logical_status	logical_status;
	struct ciss_notify_rebuild_aborted	rebuild_aborted;
	struct ciss_notify_io_error		io_error;
	struct ciss_notify_consistency_completed consistency_completed;
	u_int8_t	data[64];
    } data;
    char	message[80];
    u_int32_t	tag;
    u_int16_t	date;
    u_int16_t	year;
    u_int32_t	time;
    u_int16_t	pre_power_up_time;
    union ciss_device_address	device;
    /* XXX pads to 512 bytes */
} __packed;

/*
 * CISS config table, which describes the controller's
 * supported interface(s) and capabilities.
 *
 * This is mapped directly via PCI.
 */
struct ciss_config_table
{
    char	signature[4];		/* "CISS" */
    u_int32_t	valence;
    u_int32_t	supported_methods;
#define CISS_TRANSPORT_METHOD_READY	(1<<0)
#define CISS_TRANSPORT_METHOD_SIMPLE	(1<<1)
#define CISS_TRANSPORT_METHOD_PERF	(1<<2)
    u_int32_t	active_method;
    u_int32_t	requested_method;
    u_int32_t	command_physlimit;
    u_int32_t	interrupt_coalesce_delay;
    u_int32_t	interrupt_coalesce_count;
    u_int32_t	max_outstanding_commands;
    u_int32_t	bus_types;
#define CISS_TRANSPORT_BUS_TYPE_ULTRA2	(1<<0)
#define CISS_TRANSPORT_BUS_TYPE_ULTRA3	(1<<1)
#define CISS_TRANSPORT_BUS_TYPE_FIBRE1	(1<<8)
#define CISS_TRANSPORT_BUS_TYPE_FIBRE2	(1<<9)
    u_int32_t	transport_offset;
    char	server_name[16];
    u_int32_t	heartbeat;
    u_int32_t	host_driver;
#define CISS_DRIVER_SUPPORT_UNIT_ATTENTION	(1<<0)
#define CISS_DRIVER_QUICK_INIT			(1<<1)
#define CISS_DRIVER_INTERRUPT_ON_LOCKUP		(1<<2)
#define CISS_DRIVER_SUPPORT_MIXED_Q_TAGS	(1<<3)
#define CISS_DRIVER_HOST_IS_ALPHA		(1<<4)
#define CISS_DRIVER_MULTI_LUN_SUPPORT		(1<<5)
#define CISS_DRIVER_MESSAGE_REQUESTS_SUPPORTED	(1<<7)
#define CISS_DRIVER_DAUGHTER_ATTACHED		(1<<8)
#define CISS_DRIVER_SCSI_PREFETCH		(1<<9)
    u_int32_t	max_sg_length;		/* 31 in older firmware */
} __packed;

/*
 * Configuration table for the Performant transport.  Only 4 request queues
 * are mentioned in this table, though apparently up to 256 can exist.
 */
struct ciss_perf_config {
    uint32_t	fetch_count[8];
#define CISS_SG_FETCH_MAX	0
#define CISS_SG_FETCH_1		1
#define CISS_SG_FETCH_2		2
#define CISS_SG_FETCH_4		3
#define CISS_SG_FETCH_8		4
#define CISS_SG_FETCH_16	5
#define CISS_SG_FETCH_32	6
#define CISS_SG_FETCH_NONE	7
    uint32_t	rq_size;
    uint32_t	rq_count;
    uint32_t	rq_bank_lo;
    uint32_t	rq_bank_hi;
    struct {
	uint32_t	rq_addr_lo;
	uint32_t	rq_addr_hi;
    } __packed rq[4];
} __packed;

/*
 * In a flagrant violation of what CISS seems to be meant to be about,
 * Compaq recycle a goodly portion of their previous generation's
 * command set (and all the legacy baggage related to a design
 * originally aimed at narrow SCSI) through the Array Controller Read
 * and Array Controller Write interface.
 *
 * Command ID values here can be looked up for in the
 * publically-available documentation for the older controllers; note
 * that the command layout is necessarily different to fit within the
 * CDB.
 */
#define CISS_ARRAY_CONTROLLER_READ	0x26
#define CISS_ARRAY_CONTROLLER_WRITE	0x27

#define CISS_BMIC_ID_LDRIVE		0x10
#define CISS_BMIC_ID_CTLR		0x11
#define CISS_BMIC_ID_LSTATUS		0x12
#define CISS_BMIC_ID_PDRIVE		0x15
#define CISS_BMIC_BLINK_PDRIVE		0x16
#define CISS_BMIC_SENSE_BLINK_PDRIVE	0x17
#define CISS_BMIC_SOFT_RESET		0x40
#define CISS_BMIC_FLUSH_CACHE		0xc2
#define CISS_BMIC_ACCEPT_MEDIA		0xe0

/*
 * When numbering drives, the original design assumed that
 * drives 0-7 are on the first SCSI bus, 8-15 on the second,
 * and so forth.  In order to handle modern SCSI configurations,
 * the MSB is set in the drive ID field, in which case the
 * modulus changes from 8 to the number of supported drives
 * per SCSI bus (as obtained from the ID_CTLR command).
 * This feature is referred to as BIG_MAP support, and we assume
 * that all CISS controllers support it.
 */

#define CISS_BIG_MAP_ID(sc, bus, target)		\
	(0x80 | 					\
	 ((sc)->ciss_id->drives_per_scsi_bus * (bus)) |	\
	 (target))

#define CISS_BIG_MAP_BUS(sc, id)			\
	(((id) & 0x80) ? (((id) & ~0x80) / (sc)->ciss_id->drives_per_scsi_bus) : -1)

#define CISS_BIG_MAP_TARGET(sc, id)			\
	(((id) & 0x80) ? (((id) & ~0x80) % (sc)->ciss_id->drives_per_scsi_bus) : -1)

#define CISS_BIG_MAP_ENTRIES	128	/* number of entries in a BIG_MAP */

/*
 * In the device address of a logical volume, the bus number
 * is encoded into the logical lun volume number starting
 * at the second byte, with the first byte defining the
 * logical drive number.
 */
#define CISS_LUN_TO_BUS(x)    (((x) >> 16) & 0xFF)
#define CISS_LUN_TO_TARGET(x) ((x) & 0xFF)

/*
 * BMIC CDB
 *
 * Note that the phys_drive/res1 field is nominally the 32-bit
 * "block number" field, but the only BMIC command(s) of interest
 * implemented overload the MSB (note big-endian format here)
 * to be the physical drive ID, so we define accordingly.
 */
struct ciss_bmic_cdb {
    u_int8_t	opcode;
    u_int8_t	log_drive;
    u_int8_t	phys_drive;
    u_int8_t	res1[3];
    u_int8_t	bmic_opcode;
    u_int16_t	size;			/* big-endian */
    u_int8_t	res2;
} __packed;

/*
 * BMIC command command/return structures.
 */

/* CISS_BMIC_ID_LDRIVE */
struct ciss_bmic_id_ldrive {
    u_int16_t	block_size;
    u_int32_t	blocks_available;
    u_int8_t	drive_parameter_table[16];	/* XXX define */
    u_int8_t	fault_tolerance;
#define CISS_LDRIVE_RAID0	0
#define CISS_LDRIVE_RAID4	1
#define CISS_LDRIVE_RAID1	2
#define CISS_LDRIVE_RAID5	3
#define CISS_LDRIVE_RAID51	4
#define CISS_LDRIVE_RAIDADG	5
    u_int8_t	res1;
    u_int8_t	bios_disable_flag;
    u_int8_t	res2;
    u_int32_t	logical_drive_identifier;
    char	logical_drive_label[64];
    u_int64_t	big_blocks_available;
    u_int8_t	res3[410];
} __packed;

/* CISS_BMIC_ID_LSTATUS */
struct ciss_bmic_id_lstatus {
    u_int8_t	status;
#define CISS_LSTATUS_OK				0
#define CISS_LSTATUS_FAILED			1
#define CISS_LSTATUS_NOT_CONFIGURED		2
#define CISS_LSTATUS_INTERIM_RECOVERY		3
#define CISS_LSTATUS_READY_RECOVERY		4
#define CISS_LSTATUS_RECOVERING			5
#define CISS_LSTATUS_WRONG_PDRIVE		6
#define CISS_LSTATUS_MISSING_PDRIVE		7
#define CISS_LSTATUS_EXPANDING			10
#define CISS_LSTATUS_BECOMING_READY		11
#define CISS_LSTATUS_QUEUED_FOR_EXPANSION	12
    u_int32_t	deprecated_drive_failure_map;
    u_int8_t	res1[416];
    u_int32_t	blocks_to_recover;
    u_int8_t	deprecated_drive_rebuilding;
    u_int16_t	deprecated_remap_count[32];
    u_int32_t	deprecated_replacement_map;
    u_int32_t	deprecated_active_spare_map;
    u_int8_t	spare_configured:1;
    u_int8_t	spare_rebuilding:1;
    u_int8_t	spare_rebuilt:1;
    u_int8_t	spare_failed:1;
    u_int8_t	spare_switched:1;
    u_int8_t	spare_available:1;
    u_int8_t	res2:2;
    u_int8_t	deprecated_spare_to_replace_map[32];
    u_int32_t	deprecated_replaced_marked_ok_map;
    u_int8_t	media_exchanged;
    u_int8_t	cache_failure;
    u_int8_t	expand_failure;
    u_int8_t	rebuild_read_failure:1;
    u_int8_t	rebuild_write_failure:1;
    u_int8_t	res3:6;
    u_int8_t	drive_failure_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int16_t	remap_count[CISS_BIG_MAP_ENTRIES];
    u_int8_t	replacement_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int8_t	active_spare_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int8_t	spare_to_replace_map[CISS_BIG_MAP_ENTRIES];
    u_int8_t	replaced_marked_ok_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int8_t	drive_rebuilding;
    u_int64_t	big_blocks_to_recover;
    u_int8_t	res4[28];
} __packed;

/* CISS_BMIC_ID_CTLR */
struct ciss_bmic_id_table {
    u_int8_t	configured_logical_drives;
    u_int32_t	config_signature;
    char	running_firmware_revision[4];
    char	stored_firmware_revision[4];
    u_int8_t	hardware_revision;
    u_int8_t	res1[4];
    u_int32_t	deprecated_drive_present_map;
    u_int32_t	deprecated_external_drive_present_map;
    u_int32_t	board_id;
    u_int8_t	res2;
    u_int32_t	deprecated_non_disk_map;
    u_int8_t	res3[5];
    char	marketting_revision;
    u_int8_t	res4:3;
    u_int8_t	more_than_seven_supported:1;
    u_int8_t	res5:3;
    u_int8_t	big_map_supported:1;		/* must be set! */
    u_int8_t	res6[2];
    u_int8_t	scsi_bus_count;
    u_int32_t	res7;
    u_int32_t	controller_clock;
    u_int8_t	drives_per_scsi_bus;
    u_int8_t	big_drive_present_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int8_t	big_external_drive_present_map[CISS_BIG_MAP_ENTRIES / 8];
    u_int8_t	big_non_disk_map[CISS_BIG_MAP_ENTRIES / 8];
} __packed;

/* CISS_BMIC_ID_PDRIVE */
struct ciss_bmic_id_pdrive {
    u_int8_t	scsi_bus;
    u_int8_t	scsi_id;
    u_int16_t	block_size;
    u_int32_t	total_blocks;
    u_int32_t	reserved_blocks;
    char	model[40];
    char	serial[40];
    char	revision[8];
    u_int8_t	inquiry_bits;
    u_int8_t	res1[2];
    u_int8_t	drive_present:1;
    u_int8_t	non_disk:1;
    u_int8_t	wide:1;
    u_int8_t	synchronous:1;
    u_int8_t	narrow:1;
    u_int8_t	wide_downgraded_to_narrow:1;
    u_int8_t	ultra:1;
    u_int8_t	ultra2:1;
    u_int8_t	SMART:1;
    u_int8_t	SMART_errors_recorded:1;
    u_int8_t	SMART_errors_enabled:1;
    u_int8_t	SMART_errors_detected:1;
    u_int8_t	external:1;
    u_int8_t	configured:1;
    u_int8_t	configured_spare:1;
    u_int8_t	cache_saved_enabled:1;
    u_int8_t	res2;
    u_int8_t	res3:6;
    u_int8_t	cache_currently_enabled:1;
    u_int8_t	cache_safe:1;
    u_int8_t	res4[5];
    char	connector[2];
    u_int8_t	res5;
    u_int8_t	bay;
    u_int16_t	rpm;
    u_int8_t	drive_type;
    u_int8_t	res6[393];
} __packed;

/* CISS_BMIC_BLINK_PDRIVE */
/* CISS_BMIC_SENSE_BLINK_PDRIVE */
struct ciss_bmic_blink_pdrive {
    u_int32_t	blink_duration;		/* 10ths of a second */
    u_int32_t	duration_elapsed;	/* only for sense command  */
    u_int8_t	blinktab[256];
#define CISS_BMIC_BLINK_ALL	1
#define CISS_BMIC_BLINK_TIMED	2
    u_int8_t	res2[248];
} __packed;

/* CISS_BMIC_FLUSH_CACHE */
struct ciss_bmic_flush_cache {
    u_int16_t	flag;
#define CISS_BMIC_FLUSH_AND_ENABLE	0
#define CISS_BMIC_FLUSH_AND_DISABLE	1
    u_int8_t	res1[510];
} __packed;

#ifdef _KERNEL
/*
 * CISS "simple" transport layer.
 *
 * Note that there are two slightly different versions of this interface
 * with different interrupt mask bits.  There's nothing like consistency...
 */
#define CISS_TL_SIMPLE_BAR_REGS	0x10	/* BAR pointing to register space */
#define CISS_TL_SIMPLE_BAR_CFG	0x14	/* BAR pointing to space containing config table */

#define CISS_TL_SIMPLE_IDBR	0x20	/* inbound doorbell register */
#define CISS_TL_SIMPLE_IDBR_CFG_TABLE	(1<<0)	/* notify controller of config table update */

#define CISS_TL_SIMPLE_ISR	0x30	/* interrupt status register */
#define CISS_TL_SIMPLE_IMR	0x34	/* interrupt mask register */
#define CISS_TL_SIMPLE_INTR_OPQ_SA5	(1<<3)	/* OPQ not empty interrupt, SA5 boards */
#define CISS_TL_SIMPLE_INTR_OPQ_SA5B	(1<<2)	/* OPQ not empty interrupt, SA5B boards */

#define CISS_TL_SIMPLE_IPQ	0x40	/* inbound post queue */
#define CISS_TL_SIMPLE_OPQ	0x44	/* outbound post queue */
#define CISS_TL_SIMPLE_OPQ_EMPTY	(~(u_int32_t)0)

#define CISS_TL_SIMPLE_OSR	0x9c	/* outbound status register */
#define CISS_TL_SIMPLE_ODC	0xa0	/* outbound doorbell clear register */
#define CISS_TL_SIMPLE_ODC_CLEAR	(0x1)

#define CISS_TL_SIMPLE_CFG_BAR	0xb4	/* should be 0x14 */
#define CISS_TL_SIMPLE_CFG_OFF	0xb8	/* offset in BAR at which config table is located */

/*
 * Register access primitives.
 */
#define CISS_TL_SIMPLE_READ(sc, ofs) \
	bus_space_read_4(sc->ciss_regs_btag, sc->ciss_regs_bhandle, ofs)
#define CISS_TL_SIMPLE_WRITE(sc, ofs, val) \
	bus_space_write_4(sc->ciss_regs_btag, sc->ciss_regs_bhandle, ofs, val)

#define CISS_TL_SIMPLE_POST_CMD(sc, phys)	CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, phys)
#define CISS_TL_SIMPLE_FETCH_CMD(sc)		CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_OPQ)

#define CISS_TL_PERF_INTR_OPQ	(CISS_TL_SIMPLE_INTR_OPQ_SA5 | CISS_TL_SIMPLE_INTR_OPQ_SA5B)
#define CISS_TL_PERF_INTR_MSI	0x01

#define CISS_TL_PERF_POST_CMD(sc, cr)		CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, cr->cr_ccphys | (cr)->cr_sg_tag)
#define CISS_TL_PERF_FLUSH_INT(sc)		CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_OSR)
#define CISS_TL_PERF_CLEAR_INT(sc)		CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_ODC, CISS_TL_SIMPLE_ODC_CLEAR)
#define CISS_CYCLE_MASK		0x00000001

/* Only need one MSI/MSI-X vector */
#define CISS_MSI_COUNT	1

#define CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc) \
	CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, \
			     CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR) | (sc)->ciss_interrupt_mask)
#define CISS_TL_SIMPLE_ENABLE_INTERRUPTS(sc) \
	CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, \
			     CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR) & ~(sc)->ciss_interrupt_mask)

#endif /* _KERNEL */