linux-old/drivers/net/wireless/hermes.h
<<
>>
Prefs
   1/* hermes.h
   2 *
   3 * Driver core for the "Hermes" wireless MAC controller, as used in
   4 * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
   5 * work on the hfa3841 and hfa3842 MAC controller chips used in the
   6 * Prism I & II chipsets.
   7 *
   8 * This is not a complete driver, just low-level access routines for
   9 * the MAC controller itself.
  10 *
  11 * Based on the prism2 driver from Absolute Value Systems' linux-wlan
  12 * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  13 * (wvlan_hcf.c) library, and the NetBSD wireless driver.
  14 *
  15 * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
  16 *
  17 * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  18 *
  19 * This file distributed under the GPL, version 2.
  20 */
  21
  22#ifndef _HERMES_H
  23#define _HERMES_H
  24
  25/* Notes on locking:
  26 *
  27 * As a module of low level hardware access routines, there is no
  28 * locking. Users of this module should ensure that they serialize
  29 * access to the hermes_t structure, and to the hardware
  30*/
  31
  32#include <linux/delay.h>
  33#include <linux/if_ether.h>
  34#include <asm/byteorder.h>
  35
  36/*
  37 * Limits and constants
  38 */
  39#define         HERMES_ALLOC_LEN_MIN            (4)
  40#define         HERMES_ALLOC_LEN_MAX            (2400)
  41#define         HERMES_LTV_LEN_MAX              (34)
  42#define         HERMES_BAP_DATALEN_MAX          (4096)
  43#define         HERMES_BAP_OFFSET_MAX           (4096)
  44#define         HERMES_PORTID_MAX               (7)
  45#define         HERMES_NUMPORTS_MAX             (HERMES_PORTID_MAX+1)
  46#define         HERMES_PDR_LEN_MAX              (260)   /* in bytes, from EK */
  47#define         HERMES_PDA_RECS_MAX             (200)   /* a guess */
  48#define         HERMES_PDA_LEN_MAX              (1024)  /* in bytes, from EK */
  49#define         HERMES_SCANRESULT_MAX           (35)
  50#define         HERMES_CHINFORESULT_MAX         (8)
  51#define         HERMES_MAX_MULTICAST            (16)
  52#define         HERMES_MAGIC                    (0x7d1f)
  53
  54/*
  55 * Hermes register offsets
  56 */
  57#define         HERMES_CMD                      (0x00)
  58#define         HERMES_PARAM0                   (0x02)
  59#define         HERMES_PARAM1                   (0x04)
  60#define         HERMES_PARAM2                   (0x06)
  61#define         HERMES_STATUS                   (0x08)
  62#define         HERMES_RESP0                    (0x0A)
  63#define         HERMES_RESP1                    (0x0C)
  64#define         HERMES_RESP2                    (0x0E)
  65#define         HERMES_INFOFID                  (0x10)
  66#define         HERMES_RXFID                    (0x20)
  67#define         HERMES_ALLOCFID                 (0x22)
  68#define         HERMES_TXCOMPLFID               (0x24)
  69#define         HERMES_SELECT0                  (0x18)
  70#define         HERMES_OFFSET0                  (0x1C)
  71#define         HERMES_DATA0                    (0x36)
  72#define         HERMES_SELECT1                  (0x1A)
  73#define         HERMES_OFFSET1                  (0x1E)
  74#define         HERMES_DATA1                    (0x38)
  75#define         HERMES_EVSTAT                   (0x30)
  76#define         HERMES_INTEN                    (0x32)
  77#define         HERMES_EVACK                    (0x34)
  78#define         HERMES_CONTROL                  (0x14)
  79#define         HERMES_SWSUPPORT0               (0x28)
  80#define         HERMES_SWSUPPORT1               (0x2A)
  81#define         HERMES_SWSUPPORT2               (0x2C)
  82#define         HERMES_AUXPAGE                  (0x3A)
  83#define         HERMES_AUXOFFSET                (0x3C)
  84#define         HERMES_AUXDATA                  (0x3E)
  85
  86/*
  87 * CMD register bitmasks
  88 */
  89#define         HERMES_CMD_BUSY                 (0x8000)
  90#define         HERMES_CMD_AINFO                (0x7f00)
  91#define         HERMES_CMD_MACPORT              (0x0700)
  92#define         HERMES_CMD_RECL                 (0x0100)
  93#define         HERMES_CMD_WRITE                (0x0100)
  94#define         HERMES_CMD_PROGMODE             (0x0300)
  95#define         HERMES_CMD_CMDCODE              (0x003f)
  96
  97/*
  98 * STATUS register bitmasks
  99 */
 100#define         HERMES_STATUS_RESULT            (0x7f00)
 101#define         HERMES_STATUS_CMDCODE           (0x003f)
 102
 103/*
 104 * OFFSET register bitmasks
 105 */
 106#define         HERMES_OFFSET_BUSY              (0x8000)
 107#define         HERMES_OFFSET_ERR               (0x4000)
 108#define         HERMES_OFFSET_DATAOFF           (0x0ffe)
 109
 110/*
 111 * Event register bitmasks (INTEN, EVSTAT, EVACK)
 112 */
 113#define         HERMES_EV_TICK                  (0x8000)
 114#define         HERMES_EV_WTERR                 (0x4000)
 115#define         HERMES_EV_INFDROP               (0x2000)
 116#define         HERMES_EV_INFO                  (0x0080)
 117#define         HERMES_EV_DTIM                  (0x0020)
 118#define         HERMES_EV_CMD                   (0x0010)
 119#define         HERMES_EV_ALLOC                 (0x0008)
 120#define         HERMES_EV_TXEXC                 (0x0004)
 121#define         HERMES_EV_TX                    (0x0002)
 122#define         HERMES_EV_RX                    (0x0001)
 123
 124/*
 125 * Command codes
 126 */
 127/*--- Controller Commands --------------------------*/
 128#define         HERMES_CMD_INIT                 (0x0000)
 129#define         HERMES_CMD_ENABLE               (0x0001)
 130#define         HERMES_CMD_DISABLE              (0x0002)
 131#define         HERMES_CMD_DIAG                 (0x0003)
 132
 133/*--- Buffer Mgmt Commands --------------------------*/
 134#define         HERMES_CMD_ALLOC                (0x000A)
 135#define         HERMES_CMD_TX                   (0x000B)
 136#define         HERMES_CMD_CLRPRST              (0x0012)
 137
 138/*--- Regulate Commands --------------------------*/
 139#define         HERMES_CMD_NOTIFY               (0x0010)
 140#define         HERMES_CMD_INQUIRE              (0x0011)
 141
 142/*--- Configure Commands --------------------------*/
 143#define         HERMES_CMD_ACCESS               (0x0021)
 144#define         HERMES_CMD_DOWNLD               (0x0022)
 145
 146/*--- Debugging Commands -----------------------------*/
 147#define         HERMES_CMD_MONITOR              (0x0038)
 148#define         HERMES_MONITOR_ENABLE           (0x000b)
 149#define         HERMES_MONITOR_DISABLE          (0x000f)
 150
 151/*
 152 * Frame structures and constants
 153 */
 154
 155#define HERMES_DESCRIPTOR_OFFSET        0
 156#define HERMES_802_11_OFFSET            (14)
 157#define HERMES_802_3_OFFSET             (14+32)
 158#define HERMES_802_2_OFFSET             (14+32+14)
 159
 160struct hermes_rx_descriptor {
 161        u16 status;
 162        u32 time;
 163        u8 silence;
 164        u8 signal;
 165        u8 rate;
 166        u8 rxflow;
 167        u32 reserved;
 168} __attribute__ ((packed));
 169
 170#define HERMES_RXSTAT_ERR               (0x0003)
 171#define HERMES_RXSTAT_BADCRC            (0x0001)
 172#define HERMES_RXSTAT_UNDECRYPTABLE     (0x0002)
 173#define HERMES_RXSTAT_MACPORT           (0x0700)
 174#define HERMES_RXSTAT_PCF               (0x1000)        /* Frame was received in CF period */
 175#define HERMES_RXSTAT_MSGTYPE           (0xE000)
 176#define HERMES_RXSTAT_1042              (0x2000)        /* RFC-1042 frame */
 177#define HERMES_RXSTAT_TUNNEL            (0x4000)        /* bridge-tunnel encoded frame */
 178#define HERMES_RXSTAT_WMP               (0x6000)        /* Wavelan-II Management Protocol frame */
 179
 180struct hermes_tx_descriptor {
 181        u16 status;
 182        u16 reserved1;
 183        u16 reserved2;
 184        u32 sw_support;
 185        u8 retry_count;
 186        u8 tx_rate;
 187        u16 tx_control; 
 188} __attribute__ ((packed));
 189
 190#define HERMES_TXSTAT_RETRYERR          (0x0001)
 191#define HERMES_TXSTAT_AGEDERR           (0x0002)
 192#define HERMES_TXSTAT_DISCON            (0x0004)
 193#define HERMES_TXSTAT_FORMERR           (0x0008)
 194
 195#define HERMES_TXCTRL_TX_OK             (0x0002)        /* ?? interrupt on Tx complete */
 196#define HERMES_TXCTRL_TX_EX             (0x0004)        /* ?? interrupt on Tx exception */
 197#define HERMES_TXCTRL_802_11            (0x0008)        /* We supply 802.11 header */
 198#define HERMES_TXCTRL_ALT_RTRY          (0x0020)
 199
 200/* Inquiry constants and data types */
 201
 202#define HERMES_INQ_TALLIES              (0xF100)
 203#define HERMES_INQ_SCAN                 (0xF101)
 204#define HERMES_INQ_LINKSTATUS           (0xF200)
 205
 206struct hermes_tallies_frame {
 207        u16 TxUnicastFrames;
 208        u16 TxMulticastFrames;
 209        u16 TxFragments;
 210        u16 TxUnicastOctets;
 211        u16 TxMulticastOctets;
 212        u16 TxDeferredTransmissions;
 213        u16 TxSingleRetryFrames;
 214        u16 TxMultipleRetryFrames;
 215        u16 TxRetryLimitExceeded;
 216        u16 TxDiscards;
 217        u16 RxUnicastFrames;
 218        u16 RxMulticastFrames;
 219        u16 RxFragments;
 220        u16 RxUnicastOctets;
 221        u16 RxMulticastOctets;
 222        u16 RxFCSErrors;
 223        u16 RxDiscards_NoBuffer;
 224        u16 TxDiscardsWrongSA;
 225        u16 RxWEPUndecryptable;
 226        u16 RxMsgInMsgFragments;
 227        u16 RxMsgInBadMsgFragments;
 228        /* Those last are probably not available in very old firmwares */
 229        u16 RxDiscards_WEPICVError;
 230        u16 RxDiscards_WEPExcluded;
 231} __attribute__ ((packed));
 232
 233/* Grabbed from wlan-ng - Thanks Mark... - Jean II
 234 * This is the result of a scan inquiry command */
 235/* Structure describing info about an Access Point */
 236struct hermes_scan_apinfo {
 237        u16 channel;            /* Channel where the AP sits */
 238        u16 noise;              /* Noise level */
 239        u16 level;              /* Signal level */
 240        u8 bssid[ETH_ALEN];     /* MAC address of the Access Point */
 241        u16 beacon_interv;      /* Beacon interval ? */
 242        u16 capabilities;       /* Capabilities ? */
 243        u8 essid[32];           /* ESSID of the network */
 244        u8 rates[10];           /* Bit rate supported */
 245        u16 proberesp_rate;     /* ???? */
 246} __attribute__ ((packed));
 247/* Container */
 248struct hermes_scan_frame {
 249        u16 rsvd;                   /* ??? */
 250        u16 scanreason;             /* ??? */
 251        struct hermes_scan_apinfo aps[35];        /* Scan result */
 252} __attribute__ ((packed));
 253#define HERMES_LINKSTATUS_NOT_CONNECTED   (0x0000)  
 254#define HERMES_LINKSTATUS_CONNECTED       (0x0001)
 255#define HERMES_LINKSTATUS_DISCONNECTED    (0x0002)
 256#define HERMES_LINKSTATUS_AP_CHANGE       (0x0003)
 257#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004)
 258#define HERMES_LINKSTATUS_AP_IN_RANGE     (0x0005)
 259#define HERMES_LINKSTATUS_ASSOC_FAILED    (0x0006)
 260  
 261struct hermes_linkstatus {
 262        u16 linkstatus;         /* Link status */
 263} __attribute__ ((packed));
 264
 265// #define HERMES_DEBUG_BUFFER 1
 266#define HERMES_DEBUG_BUFSIZE 4096
 267struct hermes_debug_entry {
 268        int bap;
 269        u16 id, offset;
 270        int cycles;
 271};
 272
 273#ifdef __KERNEL__
 274
 275/* Timeouts */
 276#define HERMES_BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
 277
 278/* Basic control structure */
 279typedef struct hermes {
 280        ulong iobase;
 281        int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */
 282#define HERMES_IO       1
 283#define HERMES_MEM      0
 284        int reg_spacing;
 285#define HERMES_16BIT_REGSPACING 0
 286#define HERMES_32BIT_REGSPACING 1
 287
 288        u16 inten; /* Which interrupts should be enabled? */
 289
 290#ifdef HERMES_DEBUG_BUFFER
 291        struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE];
 292        unsigned long dbufp;
 293        unsigned long profile[HERMES_BAP_BUSY_TIMEOUT+1];
 294#endif
 295} hermes_t;
 296
 297typedef struct hermes_response {
 298        u16 status, resp0, resp1, resp2;
 299} hermes_response_t;
 300
 301/* Register access convenience macros */
 302#define hermes_read_reg(hw, off) ((hw)->io_space ? \
 303        inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
 304        readw((hw)->iobase + ( (off) << (hw)->reg_spacing )))
 305#define hermes_write_reg(hw, off, val) ((hw)->io_space ? \
 306        outw_p((val), (hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
 307        writew((val), (hw)->iobase + ( (off) << (hw)->reg_spacing )))
 308
 309#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
 310#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
 311
 312/* Function prototypes */
 313void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing);
 314int hermes_init(hermes_t *hw);
 315int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp);
 316int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
 317
 318int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
 319                       u16 id, u16 offset);
 320int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
 321                        u16 id, u16 offset);
 322int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
 323                    u16 *length, void *buf);
 324int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
 325                      u16 length, const void *value);
 326
 327/* Inline functions */
 328
 329static inline int hermes_present(hermes_t *hw)
 330{
 331        return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
 332}
 333
 334static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
 335{
 336        hw->inten = events;
 337        hermes_write_regn(hw, INTEN, events);
 338}
 339
 340static inline int hermes_enable_port(hermes_t *hw, int port)
 341{
 342        return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
 343                                 0, NULL);
 344}
 345
 346static inline int hermes_disable_port(hermes_t *hw, int port)
 347{
 348        return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), 
 349                                 0, NULL);
 350}
 351
 352/* Initiate an INQUIRE command (tallies or scan).  The result will come as an
 353 * information frame in __orinoco_ev_info() */
 354static inline int hermes_inquire(hermes_t *hw, u16 rid)
 355{
 356        return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
 357}
 358
 359#define HERMES_BYTES_TO_RECLEN(n) ( (((n)+1)/2) + 1 )
 360#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
 361
 362/* Note that for the next two, the count is in 16-bit words, not bytes */
 363static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsigned count)
 364{
 365        off = off << hw->reg_spacing;;
 366
 367        if (hw->io_space) {
 368                insw(hw->iobase + off, buf, count);
 369        } else {
 370                unsigned i;
 371                u16 *p;
 372
 373                /* This needs to *not* byteswap (like insw()) but
 374                 * readw() does byteswap hence the conversion.  I hope
 375                 * gcc is smart enough to fold away the two swaps on
 376                 * big-endian platforms. */
 377                for (i = 0, p = buf; i < count; i++) {
 378                        *p++ = cpu_to_le16(readw(hw->iobase + off));
 379                }
 380        }
 381}
 382
 383static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count)
 384{
 385        off = off << hw->reg_spacing;;
 386
 387        if (hw->io_space) {
 388                outsw(hw->iobase + off, buf, count);
 389        } else {
 390                unsigned i;
 391                const u16 *p;
 392
 393                /* This needs to *not* byteswap (like outsw()) but
 394                 * writew() does byteswap hence the conversion.  I
 395                 * hope gcc is smart enough to fold away the two swaps
 396                 * on big-endian platforms. */
 397                for (i = 0, p = buf; i < count; i++) {
 398                        writew(le16_to_cpu(*p++), hw->iobase + off);
 399                }
 400        }
 401}
 402
 403static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
 404{
 405        unsigned i;
 406
 407        off = off << hw->reg_spacing;;
 408
 409        if (hw->io_space) {
 410                for (i = 0; i < count; i++)
 411                        outw(0, hw->iobase + off);
 412        } else {
 413                for (i = 0; i < count; i++)
 414                        writew(0, hw->iobase + off);
 415        }
 416}
 417
 418#define HERMES_READ_RECORD(hw, bap, rid, buf) \
 419        (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
 420#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
 421        (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf)))
 422
 423static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 424{
 425        u16 rec;
 426        int err;
 427
 428        err = HERMES_READ_RECORD(hw, bap, rid, &rec);
 429        *word = le16_to_cpu(rec);
 430        return err;
 431}
 432
 433static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
 434{
 435        u16 rec = cpu_to_le16(word);
 436        return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
 437}
 438
 439#else /* ! __KERNEL__ */
 440
 441/* These are provided for the benefit of userspace drivers and testing programs
 442   which use ioperm() or iopl() */
 443
 444#define hermes_read_reg(base, off) (inw((base) + (off)))
 445#define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
 446
 447#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
 448#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
 449
 450/* Note that for the next two, the count is in 16-bit words, not bytes */
 451#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
 452#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
 453
 454#endif /* ! __KERNEL__ */
 455
 456#endif  /* _HERMES_H */
 457
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.