hfa384x.c
来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 2,425 行 · 第 1/5 页
C
2,425 行
} result = hfa384x_copy_from_bap( hw, hw->bap, rid, 0, &rec, sizeof(rec)); if ( result ) { WLAN_LOG_DEBUG0(3,"Call to hfa384x_copy_from_bap failed\n"); goto fail; } /* Validate the record length */ if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */ WLAN_LOG_DEBUG3(1, "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2); result = -ENODATA; goto fail; } result = hfa384x_copy_from_bap( hw, hw->bap, rid, sizeof(rec), buf, len);fail: DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_getconfig16** Performs the sequence necessary to read a 16 bit config/info item* and convert it to host order.** Arguments:* hw device structure* rid config/info record id (in host order)* val ptr to 16 bit buffer to receive value (in host order)** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val){ int result = 0; DBFENTER; result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); if ( result == 0 ) { *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); } DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_getconfig32** Performs the sequence necessary to read a 32 bit config/info item* and convert it to host order.** Arguments:* hw device structure* rid config/info record id (in host order)* val ptr to 32 bit buffer to receive value (in host order)** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val){ int result = 0; DBFENTER; result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); if ( result == 0 ) { *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); } DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig** Performs the sequence necessary to write a config/info item.** Arguments:* hw device structure* rid config/info record id (in host order)* buf host side record buffer* len buffer length (in bytes)** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len){ int result = 0; hfa384x_rec_t rec; DBFENTER; rec.rid = host2hfa384x_16(rid); rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */ /* write the record header */ result = hfa384x_copy_to_bap( hw, hw->bap, rid, 0, &rec, sizeof(rec)); if ( result ) { WLAN_LOG_DEBUG0(3,"Failure writing record header\n"); goto fail; } /* write the record data (if there is any) */ if ( len > 0 ) { result = hfa384x_copy_to_bap( hw, hw->bap, rid, sizeof(rec), buf, len); if ( result ) { WLAN_LOG_DEBUG0(3,"Failure writing record data\n"); goto fail; } } result = hfa384x_cmd_access( hw, 1, rid);fail: DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig16** Performs the sequence necessary to write a 16 bit config/info item.** Arguments:* hw device structure* rid config/info record id (in host order)* val 16 bit value to store (in host order)** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val){ int result; UINT16 value; DBFENTER; value = host2hfa384x_16(*val); result = hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16)); DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig32** Performs the sequence necessary to write a 32 bit config/info item.** Arguments:* hw device structure* rid config/info record id (in host order)* val 32 bit value to store (in host order)** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val){ int result; UINT32 value; DBFENTER; value = host2hfa384x_32(*val); result = hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32)); DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_readpda** Performs the sequence to read the PDA space. Note there is no* drvr_writepda() function. Writing a PDA is* generally implemented by a calling component via calls to * cmd_download and writing to the flash download buffer via the * aux regs.** Arguments:* hw device structure* buf buffer to store PDA in* len buffer length** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error* -ETIMEOUT timout waiting for the cmd regs to become* available, or waiting for the control reg* to indicate the Aux port is enabled.* -ENODATA the buffer does NOT contain a valid PDA.* Either the card PDA is bad, or the auxdata* reads are giving us garbage.** Side effects:** Call context:* process thread or non-card interrupt.----------------------------------------------------------------*/int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len){ int result = 0; UINT16 *pda = buf; int pdaok = 0; int morepdrs = 1; int currpdr = 0; /* word offset of the current pdr */ int i; UINT16 pdrlen; /* pdr length in bytes, host order */ UINT16 pdrcode; /* pdr code, host order */ UINT16 crc; UINT16 pdacrc; struct pdaloc { UINT32 cardaddr; UINT16 auxctl; } pdaloc[] = { { HFA3842_PDA_BASE, HFA384x_AUX_CTL_NV}, { HFA3842_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, { HFA3841_PDA_BASE, HFA384x_AUX_CTL_NV}, { HFA3841_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, { HFA3841_PDA_BOGUS_BASE, HFA384x_AUX_CTL_NV} }; DBFENTER; /* Check for aux available */ result = hfa384x_cmd_aux_enable(hw); if ( result ) { WLAN_LOG_DEBUG1(1,"aux_enable() failed. result=%d\n", result); goto failed; } /* Read the pda from each known address. */ for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) { WLAN_LOG_DEBUG2( 3, "Checking PDA@(0x%08lx,%s)\n", pdaloc[i].cardaddr, pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ? "CTL_NV" : "CTL_EXTDS"); /* Copy bufsize bytes from our current pdaloc */ hfa384x_copy_from_aux(hw, pdaloc[i].cardaddr, pdaloc[i].auxctl, buf, len); /* Test for garbage */ /* Traverse the PDR list Looking for PDA-END */ pdaok = 1; /* intially assume good */ morepdrs = 1; currpdr = 0; while ( pdaok && morepdrs ) { pdrlen = hfa384x2host_16(pda[currpdr]) * 2; pdrcode = hfa384x2host_16(pda[currpdr+1]); /* Test for completion at END record */ if ( pdrcode == HFA384x_PDR_END_OF_PDA ) { if ( pdrlen == 4 ) { morepdrs = 0; /* Calculate CRC-16 and compare to PDA * value. Note the addition of 2 words * for ENDREC.len and ENDREC.code * fields. */ crc = hfa384x_mkcrc16( (UINT8*)pda, (currpdr + 2) * sizeof(UINT16)); pdacrc =hfa384x2host_16(pda[currpdr+2]); if ( crc != pdacrc ) { WLAN_LOG_DEBUG2(3, "PDA crc failed: calc_crc=0x%04x, pdr_crc=0x%04x.\n", crc, pdacrc); pdaok = 0; } } else { WLAN_LOG_DEBUG1(3, "END record detected w/ " "len(%d) != 2, assuming bad PDA\n", pdrlen); pdaok = 0; } break; } /* Test the record length */ if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { WLAN_LOG_DEBUG4(3, "pdrlen for address #%d " "at %#lx:%#x:%d\n", i, pdaloc[i].cardaddr, pdaloc[i].auxctl, pdrlen); WLAN_LOG_DEBUG1(3,"pdrlen invalid=%d\n", pdrlen); pdaok = 0; break; } /* Move to the next pdr */ if ( morepdrs ) { /* note the access to pda[], we need words */ currpdr += hfa384x2host_16(pda[currpdr]) + 1; if (currpdr*sizeof(UINT16) > len) { WLAN_LOG_DEBUG0(3, "Didn't find PDA_END in buffer, " "trying next location.\n"); pdaok = 0; break; } } } if ( pdaok ) { WLAN_LOG_INFO2( "PDA Read from 0x%08lx in %s space.\n", pdaloc[i].cardaddr, pdaloc[i].auxctl == 0 ? "EXTDS" : pdaloc[i].auxctl == 1 ? "NV" : pdaloc[i].auxctl == 2 ? "PHY" : pdaloc[i].auxctl == 3 ? "ICSRAM" : "<bogus auxctl>"); break; } } result = pdaok ? 0 : -ENODATA; if ( result ) { WLAN_LOG_DEBUG0(3,"Failure: pda is not okay\n"); } hfa384x_cmd_aux_disable(hw);failed: DBFEXIT; return result;}/*----------------------------------------------------------------* mkpda_crc** Calculates the CRC16 for the given PDA and inserts the value* into the end record.** Arguments:* pda ptr to the PDA data structure.** Returns: * 0 - success * ~0 - failure (probably an errno)----------------------------------------------------------------*/static UINT16 hfa384x_mkcrc16(UINT8 *p, int len){ UINT16 crc = 0; UINT8 *lim = p + len; while (p < lim) { crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++]; } return crc;}/*----------------------------------------------------------------* hfa384x_drvr_ramdl_enable** Begins the ram download state. Checks to see that we're not* already in a download state and that a port isn't enabled.* Sets the download state and calls cmd_download with the * ENABLE_VOLATILE subcommand and the exeaddr argument.** Arguments:* hw device structure* exeaddr the card execution address that will be * jumped to when ramdl_disable() is called* (host order).** Returns: * 0 success* >0 f/w reported error - f/w status code* <0 driver reported error** Side effects:** Call context:* process thread ----------------------------------------------------------------*/int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr){ int result = 0; UINT16 lowaddr; UINT16 hiaddr; int i; DBFENTER; /* Check that a port isn't active */ for ( i = 0; i < HFA384x_PORTID_MAX; i++) { if ( hw->port_enabled[i] ) { WLAN_LOG_DEBUG0(1,"Can't download with a port enabled.\n"); return -EINVAL; } } /* Check that we're not already in a download state */ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { WLAN_LOG_DEBUG0(1,"Download state not disabled.\n"); return -EINVAL; } /* Retrieve the buffer loc&size and timeout */ if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, &(hw->bufinfo), sizeof(hw->bufinfo))) ) { return result; } hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, &(hw->dltimeout))) ) { return result; } hw->dltimeout = hfa384x2host_16(hw->dltimeout);#if 0WLAN_LOG_DEBUG1(1,"ramdl_enable, exeaddr=0x%08x\n", exeaddr);hw->dlstate = HFA384x_DLSTATE_RAMENABLED;#endif /* Enable the aux port */ if ( (result = hfa384x_cmd_aux_enable(hw)) ) { WLAN_LOG_DEBUG1(1,"Aux enable failed, result=%d.\n", result); return result; } /* Call the download(1,addr) function */ lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, lowaddr, hiaddr, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?