Annotation of qemu/roms/ipxe/src/drivers/net/prism2.c, revision 1.1

1.1     ! root        1: /**************************************************************************
        !             2: Etherboot -  BOOTP/TFTP Bootstrap Program
        !             3: Prism2 NIC driver for Etherboot
        !             4: 
        !             5: Written by Michael Brown of Fen Systems Ltd
        !             6: $Id$
        !             7: ***************************************************************************/
        !             8: 
        !             9: /*
        !            10:  * This program is free software; you can redistribute it and/or
        !            11:  * modify it under the terms of the GNU General Public License as
        !            12:  * published by the Free Software Foundation; either version 2, or (at
        !            13:  * your option) any later version.
        !            14:  */
        !            15: 
        !            16: FILE_LICENCE ( GPL2_OR_LATER );
        !            17: 
        !            18: #include <etherboot.h>
        !            19: #include <nic.h>
        !            20: #include <ipxe/pci.h>
        !            21: #include <ipxe/ethernet.h>
        !            22: 
        !            23: /*
        !            24:  * Hard-coded SSID
        !            25:  * Leave blank in order to connect to any available SSID
        !            26:  */
        !            27: 
        !            28: static const char hardcoded_ssid[] = "";
        !            29: 
        !            30: /*
        !            31:  * Maximum number of info packets to wait for on a join attempt.
        !            32:  * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
        !            33:  * before sending the "you are connected" packet, if the card has previously been
        !            34:  * attached to the AP.
        !            35:  *
        !            36:  * 2 is probably a sensible value, but YMMV.
        !            37:  */
        !            38: 
        !            39: #define MAX_JOIN_INFO_COUNT 2
        !            40: 
        !            41: /*
        !            42:  * Type of Prism2 interface to support
        !            43:  * If not already defined, select PLX
        !            44:  */
        !            45: #ifndef WLAN_HOSTIF
        !            46: #define WLAN_HOSTIF WLAN_PLX
        !            47: #endif
        !            48: 
        !            49: /*
        !            50:  * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
        !            51:  * We need to hack some defines in order to avoid compiling kernel-specific routines
        !            52:  */
        !            53: 
        !            54: #define __LINUX_WLAN__
        !            55: #undef __KERNEL__
        !            56: #define __I386__
        !            57: #include "wlan_compat.h"
        !            58: #include "p80211hdr.h"
        !            59: #include "hfa384x.h"
        !            60: #define BAP_TIMEOUT ( 5000 )
        !            61: 
        !            62: /*
        !            63:  * A few hacks to make the coding environment more Linux-like.  This makes it somewhat
        !            64:  * quicker to convert code from the Linux Prism2 driver.
        !            65:  */
        !            66: #include <errno.h>
        !            67: #define __le16_to_cpu(x) (x)
        !            68: #define __le32_to_cpu(x) (x)
        !            69: #define __cpu_to_le16(x) (x)
        !            70: #define __cpu_to_le32(x) (x)
        !            71: 
        !            72: #define hfa384x2host_16(n)     (__le16_to_cpu((UINT16)(n)))
        !            73: #define hfa384x2host_32(n)     (__le32_to_cpu((UINT32)(n)))
        !            74: #define host2hfa384x_16(n)     (__cpu_to_le16((UINT16)(n)))
        !            75: #define host2hfa384x_32(n)     (__cpu_to_le32((UINT32)(n)))
        !            76: 
        !            77: /*
        !            78:  * PLX9052 PCI register offsets
        !            79:  * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
        !            80:  */
        !            81: 
        !            82: #define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
        !            83: #define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
        !            84: #define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
        !            85: #define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
        !            86: #define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
        !            87: 
        !            88: #define PRISM2_PLX_ATTR_MEM_BASE       ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
        !            89: #define PRISM2_PLX_IO_BASE             ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
        !            90: 
        !            91: #define PRISM2_PCI_MEM_BASE            ( PCI_BASE_ADDRESS_0 )
        !            92: 
        !            93: /*
        !            94:  * PCMCIA CIS types
        !            95:  * Taken from cistpl.h in pcmcia-cs
        !            96:  */
        !            97: 
        !            98: #define CISTPL_VERS_1           ( 0x15 )
        !            99: #define CISTPL_END              ( 0xff )
        !           100: 
        !           101: #define CIS_STEP                ( 2 )
        !           102: #define CISTPL_HEADER_LEN       ( 2 * CIS_STEP )
        !           103: #define CISTPL_LEN_OFF          ( 1 * CIS_STEP )
        !           104: #define CISTPL_VERS_1_STR_OFF   ( 4 * CIS_STEP )
        !           105: 
        !           106: /*
        !           107:  * Prism2 constants
        !           108:  * Taken from prism2sta.c in linux-wlan-ng
        !           109:  */
        !           110: 
        !           111: #define COR_OFFSET      ( 0x3e0 )   /* COR attribute offset of Prism2 PC card */
        !           112: #define COR_VALUE       ( 0x41 )    /* Enable PC card with irq in level trigger (but interrupts disabled) */
        !           113: 
        !           114: /* NIC specific static variables */
        !           115: 
        !           116: /* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
        !           117:  * This is a dummy version that contains only the fields we are interested in.
        !           118:  */
        !           119: 
        !           120: typedef struct hfa384x
        !           121: {
        !           122:   UINT32 iobase;
        !           123:   void *membase;
        !           124:   UINT16 lastcmd;
        !           125:   UINT16 status;         /* in host order */
        !           126:   UINT16 resp0;          /* in host order */
        !           127:   UINT16 resp1;          /* in host order */
        !           128:   UINT16 resp2;          /* in host order */
        !           129:   UINT8  bssid[WLAN_BSSID_LEN];
        !           130: } hfa384x_t;
        !           131: 
        !           132: /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
        !           133: static hfa384x_t hw_global = {
        !           134:   0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
        !           135: };
        !           136: 
        !           137: /*
        !           138:  * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
        !           139:  * Taken from p80211conv.h
        !           140:  */
        !           141: 
        !           142: typedef struct wlan_llc
        !           143: {
        !           144:   UINT8   dsap;
        !           145:   UINT8   ssap;
        !           146:   UINT8   ctl;
        !           147: }  wlan_llc_t;
        !           148: 
        !           149: static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
        !           150: 
        !           151: #define WLAN_IEEE_OUI_LEN 3
        !           152: typedef struct wlan_snap
        !           153: {
        !           154:   UINT8   oui[WLAN_IEEE_OUI_LEN];
        !           155:   UINT16  type;
        !           156: } wlan_snap_t;
        !           157: 
        !           158: typedef struct wlan_80211hdr
        !           159: {
        !           160:   wlan_llc_t llc;
        !           161:   wlan_snap_t snap;
        !           162: } wlan_80211hdr_t;
        !           163: 
        !           164: /*
        !           165:  * Function prototypes
        !           166:  */
        !           167: 
        !           168: /*
        !           169:  * Hardware-level hfa384x functions
        !           170:  * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
        !           171:  * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions. 
        !           172:  */
        !           173: 
        !           174: /* Retrieve the value of one of the MAC registers. */
        !           175: static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
        !           176: {
        !           177: #if (WLAN_HOSTIF == WLAN_PLX)
        !           178:   return inw ( hw->iobase + reg );
        !           179: #elif (WLAN_HOSTIF == WLAN_PCI)
        !           180:   return readw ( hw->membase + reg );
        !           181: #endif
        !           182: }
        !           183: 
        !           184: /* Set the value of one of the MAC registers. */
        !           185: static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
        !           186: {
        !           187: #if (WLAN_HOSTIF == WLAN_PLX)
        !           188:   outw ( val, hw->iobase + reg );
        !           189: #elif (WLAN_HOSTIF == WLAN_PCI)
        !           190:   writew ( val, hw->membase + reg );
        !           191: #endif
        !           192:   return;
        !           193: }
        !           194: 
        !           195: /* 
        !           196:  * Noswap versions
        !           197:  * Etherboot is i386 only, so swap and noswap are the same...
        !           198:  */
        !           199: static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
        !           200: {
        !           201:   return hfa384x_getreg ( hw, reg );
        !           202: }
        !           203: static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
        !           204: {
        !           205:   hfa384x_setreg ( hw, val, reg );
        !           206: }
        !           207: 
        !           208: /*
        !           209:  * Low-level hfa384x functions
        !           210:  * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
        !           211:  */
        !           212: 
        !           213: /*
        !           214:  * hfa384x_docmd_wait
        !           215:  *
        !           216:  * Waits for availability of the Command register, then
        !           217:  * issues the given command.  Then polls the Evstat register
        !           218:  * waiting for command completion.
        !           219:  * Arguments:
        !           220:  *       hw              device structure
        !           221:  *       cmd             Command in host order
        !           222:  *       parm0           Parameter0 in host order
        !           223:  *       parm1           Parameter1 in host order
        !           224:  *       parm2           Parameter2 in host order
        !           225:  * Returns:
        !           226:  *       0               success
        !           227:  *       >0              command indicated error, Status and Resp0-2 are
        !           228:  *                       in hw structure.
        !           229:  */
        !           230: static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
        !           231: {
        !           232:   UINT16 reg = 0;
        !           233:   UINT16 counter = 0;
        !           234:   
        !           235:   /* wait for the busy bit to clear */ 
        !           236:   counter = 0;
        !           237:   reg = hfa384x_getreg(hw, HFA384x_CMD);
        !           238:   while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
        !           239:     reg = hfa384x_getreg(hw, HFA384x_CMD);
        !           240:     counter++;
        !           241:     udelay(10);
        !           242:   }
        !           243:   if (HFA384x_CMD_ISBUSY(reg)) {
        !           244:     printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
        !           245:     return -ETIMEDOUT;
        !           246:   }
        !           247: 
        !           248:   /* busy bit clear, write command */
        !           249:   hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
        !           250:   hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
        !           251:   hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
        !           252:   hw->lastcmd = cmd;
        !           253:   hfa384x_setreg(hw, cmd, HFA384x_CMD);
        !           254:   
        !           255:   /* Now wait for completion */
        !           256:   counter = 0;
        !           257:   reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
        !           258:   /* Initialization is the problem.  It takes about
        !           259:      100ms. "normal" commands are typically is about
        !           260:      200-400 us (I've never seen less than 200).  Longer
        !           261:      is better so that we're not hammering the bus. */
        !           262:   while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
        !           263:     reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
        !           264:     counter++;
        !           265:     udelay(200);
        !           266:   }
        !           267:   if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
        !           268:     printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
        !           269:     return -ETIMEDOUT;
        !           270:   }
        !           271: 
        !           272:   /* Read status and response */
        !           273:   hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
        !           274:   hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
        !           275:   hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
        !           276:   hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
        !           277:   hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
        !           278:   return HFA384x_STATUS_RESULT_GET(hw->status);
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * Prepare BAP for access.  Assigns FID and RID, sets offset register
        !           283:  * and waits for BAP to become available.
        !           284:  *
        !           285:  * Arguments:
        !           286:  *     hw              device structure
        !           287:  *     id              FID or RID, destined for the select register (host order)
        !           288:  *     offset          An _even_ offset into the buffer for the given FID/RID.
        !           289:  * Returns: 
        !           290:  *     0               success
        !           291:  */
        !           292: static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
        !           293: {
        !           294:   int result = 0;
        !           295:   UINT16 reg;
        !           296:   UINT16 i;
        !           297: 
        !           298:   /* Validate offset, buf, and len */
        !           299:   if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
        !           300:     result = -EINVAL;
        !           301:   } else {
        !           302:     /* Write fid/rid and offset */
        !           303:     hfa384x_setreg(hw, id, HFA384x_SELECT0);
        !           304:     udelay(10);
        !           305:     hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
        !           306:     /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
        !           307:     i = 0; 
        !           308:     do {
        !           309:       reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
        !           310:       if ( i > 0 ) udelay(2);
        !           311:       i++;
        !           312:     } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
        !           313:     if ( i >= BAP_TIMEOUT ) {
        !           314:       /* failure */
        !           315:       result = reg;
        !           316:     } else if ( HFA384x_OFFSET_ISERR(reg) ){
        !           317:       /* failure */
        !           318:       result = reg;
        !           319:     }
        !           320:   }
        !           321:   return result;
        !           322: }
        !           323: 
        !           324: /*
        !           325:  * Copy data from BAP to memory.
        !           326:  *
        !           327:  * Arguments:
        !           328:  *     hw              device structure
        !           329:  *     id              FID or RID, destined for the select register (host order)
        !           330:  *     offset          An _even_ offset into the buffer for the given FID/RID.
        !           331:  *     buf             ptr to array of bytes
        !           332:  *     len             length of data to transfer in bytes
        !           333:  * Returns: 
        !           334:  *     0               success
        !           335:  */
        !           336: static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
        !           337:                          void *buf, UINT len)
        !           338: {
        !           339:   int result = 0;
        !           340:   UINT8        *d = (UINT8*)buf;
        !           341:   UINT16 i;
        !           342:   UINT16 reg = 0;
        !           343:   
        !           344:   /* Prepare BAP */
        !           345:   result = hfa384x_prepare_bap ( hw, id, offset );
        !           346:   if ( result == 0 ) {
        !           347:     /* Read even(len) buf contents from data reg */
        !           348:     for ( i = 0; i < (len & 0xfffe); i+=2 ) {
        !           349:       *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
        !           350:     }
        !           351:     /* If len odd, handle last byte */
        !           352:     if ( len % 2 ){
        !           353:       reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
        !           354:       d[len-1] = ((UINT8*)(&reg))[0];
        !           355:     }
        !           356:   }
        !           357:   if (result) {
        !           358:     printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
        !           359:   }
        !           360:   return result;
        !           361: }
        !           362: 
        !           363: /*
        !           364:  * Copy data from memory to BAP.
        !           365:  *
        !           366:  * Arguments:
        !           367:  *     hw              device structure
        !           368:  *     id              FID or RID, destined for the select register (host order)
        !           369:  *     offset          An _even_ offset into the buffer for the given FID/RID.
        !           370:  *     buf             ptr to array of bytes
        !           371:  *     len             length of data to transfer in bytes
        !           372:  * Returns: 
        !           373:  *     0               success
        !           374:  */
        !           375: static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
        !           376:                        void *buf, UINT len)
        !           377: {
        !           378:   int result = 0;
        !           379:   UINT8        *d = (UINT8*)buf;
        !           380:   UINT16 i;
        !           381:   UINT16 savereg;
        !           382: 
        !           383:   /* Prepare BAP */
        !           384:   result = hfa384x_prepare_bap ( hw, id, offset );
        !           385:   if ( result == 0 ) {
        !           386:     /* Write even(len) buf contents to data reg */
        !           387:     for ( i = 0; i < (len & 0xfffe); i+=2 ) {
        !           388:       hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0);
        !           389:     }
        !           390:     /* If len odd, handle last byte */
        !           391:     if ( len % 2 ){
        !           392:       savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
        !           393:       result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
        !           394:       if ( result == 0 ) {
        !           395:        ((UINT8*)(&savereg))[0] = d[len-1];
        !           396:        hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
        !           397:       }
        !           398:     }
        !           399:   }
        !           400:   if (result) {
        !           401:     printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
        !           402:   }
        !           403:   return result;
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Request a given record to be copied to/from the record buffer.
        !           408:  *
        !           409:  * Arguments:
        !           410:  *     hw              device structure
        !           411:  *     write           [0|1] copy the record buffer to the given
        !           412:  *                     configuration record. (host order)
        !           413:  *     rid             RID of the record to read/write. (host order)
        !           414:  *
        !           415:  * Returns: 
        !           416:  *     0               success
        !           417:  */
        !           418: static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
        !           419: {
        !           420:   return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
        !           421: }
        !           422: 
        !           423: /*
        !           424:  * Performs the sequence necessary to read a config/info item.
        !           425:  *
        !           426:  * Arguments:
        !           427:  *     hw              device structure
        !           428:  *     rid             config/info record id (host order)
        !           429:  *     buf             host side record buffer.  Upon return it will
        !           430:  *                     contain the body portion of the record (minus the 
        !           431:  *                     RID and len).
        !           432:  *     len             buffer length (in bytes, should match record length)
        !           433:  *
        !           434:  * Returns: 
        !           435:  *     0               success
        !           436:  */
        !           437: static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
        !           438: {
        !           439:   int result = 0;
        !           440:   hfa384x_rec_t        rec;
        !           441: 
        !           442:   /* Request read of RID */
        !           443:   result = hfa384x_cmd_access( hw, 0, rid);
        !           444:   if ( result ) {
        !           445:     printf("Call to hfa384x_cmd_access failed\n");
        !           446:     return -1;
        !           447:   }
        !           448:   /* Copy out record length */
        !           449:   result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
        !           450:   if ( result ) {
        !           451:     return -1;
        !           452:   }
        !           453:   /* Validate the record length */
        !           454:   if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) {  /* note body len calculation in bytes */
        !           455:     printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
        !           456:     return -1;
        !           457:   }
        !           458:   /* Copy out record data */
        !           459:   result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
        !           460:   return result;
        !           461: }
        !           462: 
        !           463: /*
        !           464:  * Performs the sequence necessary to read a 16/32 bit config/info item
        !           465:  * and convert it to host order.
        !           466:  *
        !           467:  * Arguments:
        !           468:  *     hw              device structure
        !           469:  *     rid             config/info record id (in host order)
        !           470:  *     val             ptr to 16/32 bit buffer to receive value (in host order)
        !           471:  *
        !           472:  * Returns: 
        !           473:  *     0               success
        !           474:  */
        !           475: #if 0 /* Not actually used anywhere */
        !           476: static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
        !           477: {
        !           478:   int result = 0;
        !           479:   result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
        !           480:   if ( result == 0 ) {
        !           481:     *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
        !           482:   }
        !           483:   return result;
        !           484: }
        !           485: #endif
        !           486: #if 0 /* Not actually used anywhere */
        !           487: static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
        !           488: {
        !           489:   int result = 0;
        !           490:   result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
        !           491:   if ( result == 0 ) {
        !           492:     *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
        !           493:   }
        !           494:   return result;
        !           495: }
        !           496: #endif
        !           497: 
        !           498: /*
        !           499:  * Performs the sequence necessary to write a config/info item.
        !           500:  *
        !           501:  * Arguments:
        !           502:  *     hw              device structure
        !           503:  *     rid             config/info record id (in host order)
        !           504:  *     buf             host side record buffer
        !           505:  *     len             buffer length (in bytes)
        !           506:  *
        !           507:  * Returns: 
        !           508:  *     0               success
        !           509:  */
        !           510: static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
        !           511: {
        !           512:   int result = 0;
        !           513:   hfa384x_rec_t        rec;
        !           514: 
        !           515:   rec.rid = host2hfa384x_16(rid);
        !           516:   rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
        !           517:   /* write the record header */
        !           518:   result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
        !           519:   if ( result ) {
        !           520:     printf("Failure writing record header\n");
        !           521:     return -1;
        !           522:   }
        !           523:   /* write the record data (if there is any) */
        !           524:   if ( len > 0 ) {
        !           525:     result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
        !           526:     if ( result ) {
        !           527:       printf("Failure writing record data\n");
        !           528:       return -1;
        !           529:     }
        !           530:   }
        !           531:   /* Trigger setting of record */
        !           532:   result = hfa384x_cmd_access( hw, 1, rid);
        !           533:   return result;
        !           534: }
        !           535: 
        !           536: /*
        !           537:  * Performs the sequence necessary to write a 16/32 bit config/info item.
        !           538:  *
        !           539:  * Arguments:
        !           540:  *     hw              device structure
        !           541:  *     rid             config/info record id (in host order)
        !           542:  *     val             16/32 bit value to store (in host order)
        !           543:  *
        !           544:  * Returns: 
        !           545:  *     0               success
        !           546:  */
        !           547: static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
        !           548: {
        !           549:   UINT16 value;
        !           550:   value = host2hfa384x_16(*val);
        !           551:   return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
        !           552: }
        !           553: #if 0 /* Not actually used anywhere */
        !           554: static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
        !           555: {
        !           556:   UINT32 value;
        !           557:   value = host2hfa384x_32(*val);
        !           558:   return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
        !           559: }
        !           560: #endif
        !           561: 
        !           562: /*
        !           563:  * Wait for an event, with specified checking interval and timeout.
        !           564:  * Automatically acknolwedges events.
        !           565:  *
        !           566:  * Arguments:
        !           567:  *     hw              device structure
        !           568:  *      event_mask      EVSTAT register mask of events to wait for
        !           569:  *     event_ack       EVACK register set of events to be acknowledged if they happen (can be
        !           570:  *                     used to acknowledge "ignorable" events in addition to the "main" event)
        !           571:  *      wait            Time (in us) to wait between each poll of the register
        !           572:  *      timeout         Maximum number of polls before timing out
        !           573:  *      descr           Descriptive text string of what is being waited for
        !           574:  *                      (will be printed out if a timeout happens)
        !           575:  *
        !           576:  * Returns: 
        !           577:  *      value of EVSTAT register, or 0 on failure 
        !           578:  */
        !           579: static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
        !           580: {
        !           581:   UINT16 reg;
        !           582:   int count = 0;
        !           583:   
        !           584:   do {
        !           585:     reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
        !           586:     if ( count > 0 ) udelay(wait);
        !           587:     count++;
        !           588:   } while ( !(reg & event_mask) && count < timeout);
        !           589:   if ( count >= timeout ) {
        !           590:     printf("hfa384x: Timed out waiting for %s\n", descr);
        !           591:     return 0; /* Return failure */
        !           592:   }
        !           593:   /* Acknowledge all events that we were waiting on */
        !           594:   hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
        !           595:   return reg;
        !           596: }
        !           597: 
        !           598: /**************************************************************************
        !           599: POLL - Wait for a frame
        !           600: ***************************************************************************/
        !           601: static int prism2_poll(struct nic *nic, int retrieve)
        !           602: {
        !           603:   UINT16 reg;
        !           604:   UINT16 rxfid;
        !           605:   UINT16 result;
        !           606:   hfa384x_rx_frame_t rxdesc;
        !           607:   hfa384x_t *hw = &hw_global;
        !           608:   
        !           609:   /* Check for received packet */
        !           610:   reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
        !           611:   if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
        !           612:     /* No packet received - return 0 */
        !           613:     return 0;
        !           614:   }
        !           615: 
        !           616:   if ( ! retrieve ) return 1;
        !           617: 
        !           618:   /* Acknowledge RX event */
        !           619:   hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
        !           620:   /* Get RX FID */  
        !           621:   rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
        !           622:   /* Get the descriptor (including headers) */
        !           623:   result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
        !           624:   if ( result ) {
        !           625:     return 0; /* fail */
        !           626:   }
        !           627:   /* Byte order convert once up front. */
        !           628:   rxdesc.status = hfa384x2host_16(rxdesc.status);
        !           629:   rxdesc.time = hfa384x2host_32(rxdesc.time);
        !           630:   rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
        !           631: 
        !           632:   /* Fill in nic->packetlen */
        !           633:   nic->packetlen = rxdesc.data_len;
        !           634:   if ( nic->packetlen > 0 ) {
        !           635:     /* Fill in nic->packet */
        !           636:     /*
        !           637:      * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
        !           638:      * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
        !           639:      * header), so we use a quick hack to achieve this.
        !           640:      */
        !           641:     result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
        !           642:                                   nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
        !           643:     if ( result ) {
        !           644:       return 0; /* fail */
        !           645:     }
        !           646:   }
        !           647:   return 1; /* Packet successfully received */
        !           648: }
        !           649: 
        !           650: /**************************************************************************
        !           651: TRANSMIT - Transmit a frame
        !           652: ***************************************************************************/
        !           653: static void prism2_transmit(
        !           654:                            struct nic *nic,
        !           655:                            const char *d,                      /* Destination */
        !           656:                            unsigned int t,                     /* Type */
        !           657:                            unsigned int s,                     /* size */
        !           658:                            const char *p)                      /* Packet */
        !           659: {
        !           660:   hfa384x_t *hw = &hw_global;
        !           661:   hfa384x_tx_frame_t txdesc;
        !           662:   wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
        !           663:   UINT16 fid;
        !           664:   UINT16 status;
        !           665:   int result;
        !           666: 
        !           667:   // Request FID allocation
        !           668:   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
        !           669:   if (result != 0) {
        !           670:     printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
        !           671:     return;
        !           672:   }
        !           673:   if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
        !           674:   fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
        !           675: 
        !           676:   /* Build Tx frame structure */
        !           677:   memset(&txdesc, 0, sizeof(txdesc));
        !           678:   txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1)        !           679:                                       HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
        !           680:   txdesc.frame_control =  host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
        !           681:                                       WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
        !           682:                                       WLAN_SET_FC_TODS(1) );
        !           683:   memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
        !           684:   memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
        !           685:   memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
        !           686:   txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
        !           687:   /* Set up SNAP header */
        !           688:   /* Let OUI default to RFC1042 (0x000000) */
        !           689:   p80211hdr.snap.type = htons(t);
        !           690:   
        !           691:   /* Copy txdesc, p80211hdr and payload parts to FID */
        !           692:   result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
        !           693:   if ( result ) return; /* fail */
        !           694:   result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
        !           695:   if ( result ) return; /* fail */
        !           696:   result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s );
        !           697:   if ( result ) return; /* fail */
        !           698: 
        !           699:   /* Issue Tx command */
        !           700:   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
        !           701:   if ( result != 0 ) {
        !           702:     printf("hfa384x: Transmit failed with result %#hx.\n", result);
        !           703:     return;
        !           704:   }
        !           705:   
        !           706:   /* Wait for transmit completion (or exception) */
        !           707:   result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
        !           708:                                  200, 500, "Tx to complete\n" );
        !           709:   if ( !result ) return; /* timeout failure */
        !           710:   if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
        !           711:     fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
        !           712:     printf ( "Tx exception occurred with fid %#hx\n", fid );
        !           713:     result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
        !           714:     if ( result ) return; /* fail */
        !           715:     printf("hfa384x: Tx error occurred (status %#hx):\n", status);
        !           716:     if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
        !           717:     if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
        !           718:     if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
        !           719:     if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
        !           720:     if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
        !           721:     return; /* fail */
        !           722:   }
        !           723: }
        !           724: 
        !           725: /**************************************************************************
        !           726: DISABLE - Turn off ethernet interface
        !           727: ***************************************************************************/
        !           728: static void prism2_disable ( struct nic *nic __unused ) {
        !           729:   /* put the card in its initial state */
        !           730: }
        !           731: 
        !           732: /**************************************************************************
        !           733: IRQ - Enable, Disable, or Force interrupts
        !           734: ***************************************************************************/
        !           735: static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           736: {
        !           737:   switch ( action ) {
        !           738:   case DISABLE :
        !           739:     break;
        !           740:   case ENABLE :
        !           741:     break;
        !           742:   case FORCE :
        !           743:     break;
        !           744:   }
        !           745: }
        !           746: 
        !           747: /**************************************************************************
        !           748: Operations table
        !           749: ***************************************************************************/
        !           750: static struct nic_operations prism2_operations = {
        !           751:        .connect        = dummy_connect,
        !           752:        .poll           = prism2_poll,
        !           753:        .transmit       = prism2_transmit,
        !           754:        .irq            = prism2_irq,
        !           755: };
        !           756: 
        !           757: /**************************************************************************
        !           758: PROBE - Look for an adapter, this routine's visible to the outside
        !           759: You should omit the last argument struct pci_device * for a non-PCI NIC
        !           760: ***************************************************************************/
        !           761: static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
        !           762:   int result;
        !           763:   UINT16 tmp16 = 0;
        !           764:   UINT16 infofid;
        !           765:   hfa384x_InfFrame_t inf;
        !           766:   char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
        !           767:   int info_count = 0;
        !           768: 
        !           769:   nic->irqno  = 0;
        !           770: 
        !           771:   /* Initialize card */
        !           772:   result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
        !           773:   if ( result ) printf ( "Initialize command returned %#hx\n", result );
        !           774:   hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
        !           775:   hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
        !           776: 
        !           777:   DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
        !           778: 
        !           779:   /* Retrieve MAC address (and fill out nic->node_addr) */
        !           780:   hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
        !           781: 
        !           782:   /* Prepare card for autojoin */
        !           783:   /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
        !           784:   tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
        !           785:   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
        !           786:   if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
        !           787:   tmp16 = 0x000f; /* Set transmit rate(?) */
        !           788:   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
        !           789:   if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
        !           790:   tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
        !           791:   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
        !           792:   if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
        !           793:   /* Set SSID */
        !           794:   memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
        !           795:   for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
        !           796:   ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
        !           797:   result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
        !           798:   if ( result ) printf ( "Set SSID command returned %#hx\n", result );
        !           799:   tmp16 = 1; /* Set port type to ESS port */
        !           800:   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
        !           801:   if ( result ) printf ( "Set port type command returned %#hx\n", result );
        !           802:   /* Enable card */
        !           803:   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
        !           804:   if ( result ) printf ( "Enable command returned %#hx\n", result );
        !           805: 
        !           806:   do {
        !           807:     /* Increment info_count, abort if too many attempts.
        !           808:      * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
        !           809:      */
        !           810:     info_count++;
        !           811:     if ( info_count > MAX_JOIN_INFO_COUNT ) {
        !           812:       printf ( "Too many failed attempts - aborting\n" );
        !           813:       return 0;
        !           814:     }
        !           815: 
        !           816:     /* Wait for info frame to indicate link status */
        !           817:     if ( sizeof(hardcoded_ssid) == 1 ) {
        !           818:       /* Empty SSID => join to any SSID */
        !           819:       printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
        !           820:     } else {
        !           821:       printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
        !           822:     }
        !           823:     
        !           824:     if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
        !           825:     printf("done\n");
        !           826:     infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
        !           827:     /* Retrieve the length */
        !           828:     result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16));
        !           829:     if ( result ) return 0; /* fail */
        !           830:     inf.framelen = hfa384x2host_16(inf.framelen);
        !           831:     /* Retrieve the rest */
        !           832:     result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16),
        !           833:                                    &(inf.infotype), inf.framelen * sizeof(UINT16));
        !           834:     if ( result ) return 0; /* fail */
        !           835:     if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
        !           836:       /* Not a Link Status info frame: die */
        !           837:       printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
        !           838:       return 0;
        !           839:     }
        !           840:     inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
        !           841:     if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
        !           842:       /* Link not connected - retry */
        !           843:       printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
        !           844:     }
        !           845:   } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
        !           846:     
        !           847:   /* Retrieve BSSID and print Connected message */
        !           848:   result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
        !           849: 
        !           850:   DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
        !           851:   DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
        !           852:   
        !           853:   /* point to NIC specific routines */
        !           854:   nic->nic_op  = &prism2_operations;
        !           855:   return 1;
        !           856: }
        !           857: 

unix.superglobalmegacorp.com

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