Annotation of qemu/roms/ipxe/src/drivers/net/prism2.c, revision 1.1.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.