?? am930hw.c
字號:
return result;}/*----------------------------------------------------------------* am930hw_mibset** I/F function used by mac and mgr to set the values of MIB* elements.** TODO: for now this function operates on entire sutro MIB structures.* TODO: need to make the function work on individual elements** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibset( am930hw_t *hw, UINT32 mibsec, UINT32 offset, UINT32 len, void *buf){ UINT32 result = AM930HW_SUCCESS; sucmd_set_mib_var_t cmd; am930hw_cmd_result_t cmd_result; DBFENTER; memset( &cmd, 0, sizeof(cmd)); cmd.type = mibsec; cmd.size = len; cmd.index = offset; memcpy( cmd.data, buf, len); cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_SET_MIB_VAR, &cmd, sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { DBPRT( DBFWCMD, "SetMIB failed!\n"); result = AM930HW_FAILURE; } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_mibsetitem** I/F function used by mac and mgr to set the values of MIB* items.** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibsetitem( am930hw_t *hw, UINT32 itemid, void *buf, UINT32 len){ UINT32 result = AM930HW_SUCCESS; DBFENTER; result = am930hw_mibset( hw, MI_SEC(itemid), MI_OFF(itemid), MI_SZ(itemid), buf); 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 = 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 ) { printk( KERN_DEBUG "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 = 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 ) { printk( KERN_DEBUG "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: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_txdata( am930hw_t* hw, UINT8 *buf, UINT32 len, UINT32 rate){ UINT32 result = AM930HW_SUCCESS; UINT32 slot; UINT8 state; DBFENTER; if ( buf == NULL || len > AM930_MAX_TXDATA ) { result = AM930HW_FAILURE; } else { /* Test if there is room in the queue */ state = read8(hw, hw->tx_tail + TXD_OFF_STATE); if ( !SUTXD_ST_IS_HOSTOWN(state) ) { /* printk(KERN_DEBUG"f/w tx queue full!\n"); */ result = AM930HW_FAILURE; } else { /* if so, update the tail pointer */ slot = hw->tx_tail; hw->tx_tail = read32(hw, hw->tx_tail + TXD_OFF_NEXT); /* copy the frame to card memory */ writecard(hw, slot + sizeof(am930tx_desc_t), buf, len); /* set the offset and len */ write32(hw, slot + TXD_OFF_START_FRAME, slot + sizeof(am930tx_desc_t)); write16(hw, slot + TXD_OFF_LEN, len); 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); /* give sutro ownership of the descriptor */ write8(hw, slot + TXD_OFF_STATE, SUTXD_ST_FWOWN); } } DBFEXIT; return result;}/*----------------------------------------------------------------* 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; if ( test_and_set_bit(0, &mem->lock) == 0) { 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++; } clear_bit(0, &mem->lock); } 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; if ( test_and_set_bit(0, &mem->lock) == 0) { 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; clear_bit(0, &mem->lock); } 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 ) { UINT8 * dp = (UINT8 *) buf; volatile UINT8 * sp = ((volatile UINT8 *) hw->membase) + cardaddr; while( len-- != 0 ) { *dp++ = readb(sp++); udelay(am930_iodelay); } } else { UINT8 byte; INT i; u_long flags; UINT8 lmal; UINT8 lmau; /* 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 */ save_flags(flags); cli(); lmal = inb( LMAL(hw)); lmau = inb( LMAU(hw)); /* write the address */ outb( (cardaddr) & 0x00ff, LMAL(hw)); udelay(am930_iodelay); outb( ((cardaddr) & 0x7f00) >> 8, LMAU(hw)); udelay(am930_iodelay); sti(); restore_flags(flags); /* now, copy the data */ for ( i = 0; i < len; i++) { /* retrieve the byte */ ((UINT8*)buf)[i] = inb( DPLL(hw) ); udelay(am930_iodelay); } /* restore the address regs */ save_flags(flags); cli(); outb( lmal, LMAL(hw)); udelay(am930_iodelay); outb( lmau, LMAU(hw)); udelay(am930_iodelay); sti(); restore_flags(flags); }}void writecard( am930hw_t *hw, UINT32 cardaddr, void *buf, UINT32 len){ if ( hw->usemem ) { UINT8 * sp = (UINT8 *) buf; volatile UINT8 * dp = ((volatile UINT8 *) hw->membase) + cardaddr; while( len-- != 0 ) { writeb( *sp++, dp++ ); udelay(am930_iodelay); } } else { UINT8 byte; INT i; u_long flags; UINT8 lmal; UINT8 lmau; /* 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 */ save_flags(flags); cli(); lmal = inb( LMAL(hw)); lmau = inb( LMAU(hw)); /* write the address */ outb( (cardaddr) & 0x00ff, LMAL(hw)); udelay(am930_iodelay); outb( ((cardaddr) & 0x7f00) >> 8, LMAU(hw)); udelay(am930_iodelay); sti(); restore_flags(flags); /* now, copy the data */ for ( i = 0; i < len; i++) { /* set the byte */ outb( ((UINT8*)buf)[i], DPLL(hw) ); udelay(am930_iodelay); } /* restore the address regs */ save_flags(flags); cli(); outb( lmal, LMAL(hw)); udelay(am930_iodelay); outb( lmau, LMAU(hw)); udelay(am930_iodelay); sti(); restore_flags(flags); }}UINT8 read8( am930hw_t *hw, UINT32 cardaddr ) { UINT8 result; readcard( hw, cardaddr, &result, 1); return result;}UINT16 read16( am930hw_t *hw, UINT32 cardaddr ) { UINT16 result; readcard( hw, cardaddr, &result, 2); return result;}UINT32 read32( am930hw_t *hw, UINT32 cardaddr ) { UINT32 result; readcard( hw, cardaddr, &result, 4); return result;}void write8( am930hw_t *hw, UINT32 cardaddr, UINT8 val ){ writecard( hw, cardaddr, &val, 1);}void write16( am930hw_t *hw, UINT32 cardaddr, UINT16 val ){ writecard( hw, cardaddr, &val, 2);}void write32( am930hw_t *hw, UINT32 cardaddr, UINT32 val ){ writecard( hw, cardaddr, &val, 4);}void am930db_prrxdesc( am930rx_desc_t *desc){ printk(KERN_DEBUG"rxd:"); printk("nxt:%lx ", desc->next); printk("st:%02x ", desc->state); printk("ss:%02x ", desc->rssi); printk("ch:%d ", desc->index_or_ch); printk("lt:%ld ", desc->local_time); printk("dp:%lx ", desc->rx_start_frame); printk("l:%d ", desc->rx_len); printk("r:%x\n", desc->rate);}/*#ifdef DBMSG_ENABLED #include "am930hw_db.c"#endif*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -