Annotation of Gnu-Mach/linux/pcmcia-cs/wireless/hermes.h, revision 1.1

1.1     ! root        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 <[email protected]>
        !            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: 
        !           160: struct 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: 
        !           180: struct 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: 
        !           206: struct 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 */
        !           236: struct 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 */
        !           248: struct 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:   
        !           261: struct hermes_linkstatus {
        !           262:        u16 linkstatus;         /* Link status */
        !           263: } __attribute__ ((packed));
        !           264: 
        !           265: // #define HERMES_DEBUG_BUFFER 1
        !           266: #define HERMES_DEBUG_BUFSIZE 4096
        !           267: struct 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 */
        !           279: typedef struct hermes {
        !           280:        unsigned long 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: 
        !           297: typedef 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 */
        !           313: void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing);
        !           314: int hermes_init(hermes_t *hw);
        !           315: int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp);
        !           316: int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
        !           317: 
        !           318: int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
        !           319:                       u16 id, u16 offset);
        !           320: int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
        !           321:                        u16 id, u16 offset);
        !           322: int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
        !           323:                    u16 *length, void *buf);
        !           324: int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
        !           325:                      u16 length, const void *value);
        !           326: 
        !           327: /* Inline functions */
        !           328: 
        !           329: static inline int hermes_present(hermes_t *hw)
        !           330: {
        !           331:        return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
        !           332: }
        !           333: 
        !           334: static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
        !           335: {
        !           336:        hw->inten = events;
        !           337:        hermes_write_regn(hw, INTEN, events);
        !           338: }
        !           339: 
        !           340: static 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: 
        !           346: static 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() */
        !           354: static 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 */
        !           363: static 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: 
        !           383: static 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: 
        !           403: static 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: 
        !           423: static 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: 
        !           433: static 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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.