📄 am930hw.c
字号:
DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_sync** Helper function to send the sutro SYNC command. ** returns: AM930HW_CMD_SUCCESS or* AM930HW_CMD_SYNCFAILED----------------------------------------------------------------*/UINT32 am930hw_sync( am930hw_t *hw, UINT32 ch, UINT32 startBSS, wlan_bss_ts_t ts, UINT32 ref_time ){ UINT32 result = AM930HW_CMD_SUCCESS; sucmd_sync_t cmd; am930hw_cmd_result_t cmd_result; DBFENTER; memset( &cmd, 0, sizeof(cmd)); /* values from arguments */ cmd.set_or_ch = ch; cmd.start_BSS = startBSS; cmd.ref_time = host2amd32(ref_time); if ( ts != NULL ) { memcpy( &cmd.bss_timestamp, ts, WLAN_BSS_TS_LEN); } else { memset( &cmd.bss_timestamp, 0, WLAN_BSS_TS_LEN); }/* cmd.pattern = 5; cmd.index = 1; cmd.dwell_interval = 0x3c;*/ cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_SYNC, &cmd, sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_ERROR0("sync command failed!\n"); result = AM930HW_CMD_SYNCFAILED; } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_tx_enable** Helper function to send the sutro INIT_TX command. * ASSUMPTION: The queue heads have already been set in the* members of the object.** returns: AM930HW_CMD_SUCCESS or* AM930HW_CMD_INITTXFAILED----------------------------------------------------------------*/UINT32 am930hw_tx_enable(am930hw_t *hw){ UINT32 result = AM930HW_CMD_SUCCESS; sucmd_init_tx_t cmd; am930hw_cmd_result_t cmd_result; int i; DBFENTER; /* Lets zero the last complete block */ for ( i = 0; i < 5; i++) { write32(hw, hw->txcmplt + (i * sizeof(UINT32)), 0); } /* Now send the init_tx command */ memset( &cmd, 0, sizeof(cmd)); cmd.data_desc = host2amd32(hw->tx_tail); cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_INIT_TX, &cmd, sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_ERROR0("init_tx failed!\n"); result = AM930HW_CMD_INITTXFAILED; } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_txdata** I/F function to send a packet via the sutro data queue.* rate is in 100Kbps.** returns: 0 - pkt was handed to f/w and more tx buffers avail* >0 - pkt was handed to f/w and no more tx buffers avail* <0 - pkt was not sent due to no tx buffers avail----------------------------------------------------------------*/UINT32 am930hw_txdata( am930hw_t* hw, wlan_pb_t *pb, UINT32 rate){ UINT32 result = 0; UINT32 slot; UINT8 state; wlan_flags_t flags; UINT writeaddr; UINT totallen = 0; DBFENTER; if ( pb == NULL ) { result = 0; /* bogus success */ } else { WLAN_INT_DISABLE(flags); /* Test if there is room in the queue */ state = read8(hw, hw->tx_tail + TXD_OFF_STATE); WLAN_INT_ENABLE(flags); if ( !SUTXD_ST_IS_HOSTOWN(state) ) { WLAN_LOG_DEBUG0(1, "f/w tx queue full, frame not tx'd.\n"); result = -1; /* no tx, no buffers */ } else { /* if so, update the tail pointer */ slot = hw->tx_tail; hw->tx_tail = read32(hw, hw->tx_tail + TXD_OFF_NEXT); writeaddr = slot + sizeof(am930tx_desc_t); if ( pb->ethhostbuf != NULL ) { /* It's a converted frame with pieces in multiple bufs */ /* write the 802.11 header */ writecard( hw, writeaddr, pb->p80211buf, WLAN_HDR_A3_LEN); totallen = WLAN_HDR_A3_LEN; writeaddr += WLAN_HDR_A3_LEN; WLAN_HEX_DUMP(3, "txf1.1", pb->p80211buf, WLAN_HDR_A3_LEN); /* is it encrypted ? */ if ( pb->wep_iscrypt ) { /* write the IV */ writecard( hw, writeaddr, (UINT8*)&(pb->wep_iv), sizeof(pb->wep_iv)); totallen += sizeof(pb->wep_iv); writeaddr += sizeof(pb->wep_iv); WLAN_HEX_DUMP(3, "txf1.2", &(pb->wep_iv), sizeof(pb->wep_iv)); } /* Now write any remaining in p80211buf */ if ( pb->p80211buflen > WLAN_HDR_A3_LEN) { writecard( hw, writeaddr, pb->p80211buf + WLAN_HDR_A3_LEN, pb->p80211buflen - WLAN_HDR_A3_LEN); totallen += (pb->p80211buflen - WLAN_HDR_A3_LEN); writeaddr += (pb->p80211buflen - WLAN_HDR_A3_LEN); WLAN_HEX_DUMP(3, "txf1.3", pb->p80211buf + WLAN_HDR_A3_LEN, pb->p80211buflen - WLAN_HDR_A3_LEN); } /* It's a converted frame, write the payload from p80211 */ writecard( hw, writeaddr, pb->p80211_payload, pb->p80211_payloadlen); totallen += pb->p80211_payloadlen; writeaddr += pb->p80211_payloadlen; WLAN_HEX_DUMP(3, "txf1.4", pb->p80211_payload, pb->p80211_payloadlen); /* is it encrypted ? */ if ( pb->wep_iscrypt ) { /* write the ICV */ writecard( hw, writeaddr, (UINT8*)&(pb->wep_icv), sizeof(pb->wep_icv)); totallen += sizeof(pb->wep_icv); writeaddr += sizeof(pb->wep_icv); WLAN_HEX_DUMP(3, "txf1.5", (UINT8*)&(pb->wep_icv), sizeof(pb->wep_icv)); } } else { /* write the 802.11 header */ writecard( hw, writeaddr, pb->p80211buf, WLAN_HDR_A3_LEN); totallen = WLAN_HDR_A3_LEN; writeaddr += WLAN_HDR_A3_LEN; WLAN_HEX_DUMP(3, "txf2.1", pb->p80211buf, WLAN_HDR_A3_LEN); /* is it encrypted ? */ if ( pb->wep_iscrypt ) { /* write the IV */ writecard( hw, writeaddr, (UINT8*)&(pb->wep_iv), sizeof(pb->wep_iv)); totallen += sizeof(pb->wep_iv); writeaddr += sizeof(pb->wep_iv); WLAN_HEX_DUMP(3, "txf2.2", &(pb->wep_iv), sizeof(pb->wep_iv)); } /* write the body */ writecard( hw, writeaddr, pb->p80211_payload, pb->p80211_payloadlen); totallen += pb->p80211_payloadlen; writeaddr += pb->p80211_payloadlen; WLAN_HEX_DUMP(3, "txf2.3", pb->p80211_payload, pb->p80211_payloadlen); /* is it encrypted ? */ if ( pb->wep_iscrypt ) { /* write the ICV */ writecard( hw, writeaddr, (UINT8*)&(pb->wep_icv), sizeof(pb->wep_icv)); totallen += sizeof(pb->wep_icv); writeaddr += sizeof(pb->wep_icv); WLAN_HEX_DUMP(3, "txf2.4", (UINT8*)&(pb->wep_icv), sizeof(pb->wep_icv)); } } /* set the offset and len */ WLAN_LOG_DEBUG1(3, "totallen=%d.\n", totallen); write32(hw, slot + TXD_OFF_START_FRAME, slot + sizeof(am930tx_desc_t)); #ifdef DB_TX_READBACK { UINT8 buf[2000]; readcard(hw, slot+sizeof(am930tx_desc_t), buf, totallen); WLAN_HEX_DUMP(2,"tx rdback:", buf, totallen); } #endif write16(hw, slot + TXD_OFF_LEN, totallen); write8(hw, slot + TXD_OFF_SIFS_ATTEMPTS, 0); write8(hw, slot + TXD_OFF_SIFS_FAILURES, 0); write8(hw, slot + TXD_OFF_DIFS_ATTEMPTS, 0); write8(hw, slot + TXD_OFF_DIFS_FAILURES, 0); write8(hw, slot + TXD_OFF_RTS_ATTEMPTS, 0); write8(hw, slot + TXD_OFF_DATA_ATTEMPTS, 0); write8(hw, slot + TXD_OFF_TX_CNTL, 0); write8(hw, slot + TXD_OFF_RATE, rate); write32(hw, slot + TXD_OFF_HOST, 1); /* give sutro ownership of the descriptor */ write8(hw, slot + TXD_OFF_STATE, SUTXD_ST_FWOWN); hw->used_txbuf++; result = (hw->used_txbuf >= hw->ntxbuf) ? 1 : 0; #ifdef WLAN_INCLUDE_SNIF if ( hw->mac->snifflags & SNIFFLAG_SNIFTX ) { am930mac_snifframe(hw->mac, pb, NULL); } #endif } /* WLAN_INT_ENABLE(flags); */ } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_txkick** If there is space in the f/w queue, generate a 'kicker' * ontxcomplete for the mac.** returns: nothing----------------------------------------------------------------*/void am930hw_txkick( am930hw_t* hw ){ wlan_flags_t flags; WLAN_INT_DISABLE(flags); if ( hw->used_txbuf < hw->ntxbuf ) { am930mac_ontxcomplete(hw->mac, 0xffffffffUL); } WLAN_INT_ENABLE(flags); return;}/*----------------------------------------------------------------* am930mem_init** Initializes a structure to handle _very_ simple memory * management. The structure contains a bitarray that's used* to indicate the alloc/free state of each fragment of a block* of memory. The region of memory is identified by the start and* len members. This implementation is used to manage the* tx buffer memory on the PRISM card.** Note: If len is not evenly divisible by sizeof(mem->bits)*8, then* there will be a small chunk of memory at the end of the* managed region that will never be allocated.** returns: nothing----------------------------------------------------------------*/void am930mem_init( am930mem_t *mem, UINT32 start, UINT32 len){ memset( mem, 0, sizeof(*mem)); mem->start = start; mem->len = len; mem->fragsize = len / (sizeof(mem->bits) * 8);}/*----------------------------------------------------------------* am930mem_alloc** Tests the structure lock. If set, returns NULL* Searches the bitarray for the appropriate sized chunk,* If found* sets the bits* unlocks the structure* returns the offset* else* unlocks the structure* returns NULL** Note: LSb in mem->bits corresponds to fragment at address mem->start* Note: mem->start can't be zero* Note: len of alloc'd region isn't saved, caller _must_ save it!** returns: 0 on failure, non-zero on success----------------------------------------------------------------*/UINT32 am930mem_alloc( am930mem_t *mem, UINT32 size ){ UINT32 amask; UINT32 nbits; INT i; UINT32 allocaddr = 0; wlan_flags_t flags; WLAN_INT_DISABLE(flags); if ( mem->lock == 0) { mem->lock = 1; nbits = size / mem->fragsize; nbits += ((size % mem->fragsize) ? 1 : 0); amask = ((UINT32)0xffffffff) >> ((sizeof(mem->bits) * 8) - nbits); allocaddr = 0; i = 0; while (allocaddr == 0 && i < ((sizeof(mem->bits) * 8) - nbits) ) { if ( (amask & mem->bits) == 0 ) { mem->bits |= amask; allocaddr = mem->start + (mem->fragsize * i); } amask = amask << 1; i++; } WLAN_INT_ENABLE(flags); mem->lock = 0; } else { WLAN_LOG_DEBUG0(1, "failed! mem mgr locked.\n"); } WLAN_INT_ENABLE(flags); return allocaddr;}/*----------------------------------------------------------------* am930mem_free** Tests the structure lock. If set, returns the value of p* clears the bits associated with the fragments in p,* returns NULL** returns: 0 on failure, non-zero on success----------------------------------------------------------------*/UINT32 am930mem_free( am930mem_t *mem, UINT32 p, UINT32 size){ UINT32 amask; UINT32 nbits; UINT32 lshift; wlan_flags_t flags; WLAN_INT_DISABLE(flags); if ( mem->lock == 0) { mem->lock = 1; nbits = size / mem->fragsize; nbits += ((size % mem->fragsize) ? 1 : 0); amask = ((UINT32)0xffffffff) >> ((sizeof(mem->bits)*8) - nbits); lshift = p / mem->fragsize; amask = amask << lshift; mem->bits &= ~amask; WLAN_INT_ENABLE(flags); } else { WLAN_LOG_DEBUG0(1, "failed! mem mgr locked.\n"); p = 0UL; } WLAN_INT_ENABLE(flags); return p;}/*----------------------------------------------------------------* readcard, writecard, * read8, read16, read32, * write8, write16, write32** Functions to read/write to the 'shared' memory on the card.* These functions are abstracted here so we can choose between* either the io register or memory mapped access to the card * memory.** The 8, 16, and 32 functions are for reading/writing bytes, * halfwords and words respectively.*----------------------------------------------------------------*/void readcard( am930hw_t *hw, UINT32 cardaddr, void *buf, UINT32 len){ if ( hw->usemem ) { #if (WLAN_OS == WLAN_LINUX_KERNEL) UINT8 * dp = (UINT8 *) buf; volatile UINT8 *sp = ((volatile UINT8*) hw->membase) + cardaddr; while( len-- != 0 ) { *dp++ = readb(sp++); udelay(am930_iodelay); } #else memcpy(buf, ((volatile UINT8 *) hw->membase) + cardaddr, len); #endif } else { UINT8 byte; INT i; wlan_flags_t flags; UINT8 lmal; UINT8 lmau; UINT16 scardaddr; /* set bank select and flash deselect */ byte = inb_p(BSS(hw)); byte &= ~0x38; outb_p(byte, BSS(hw)); /* save the address regs and set the new address */ WLAN_INT_DISABLE(flags); lmal = inb( LMAL(hw)); lmau = inb( LMAU(hw)); /* if necessary, mess with the byte order */ scardaddr = cardaddr; scardaddr =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -