📄 hfa384x.c
字号:
* 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, 0); if ( result ) { WLAN_LOG_DEBUG(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_DEBUG( 3, "Checking PDA@(0x%08x,%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_DEBUG(3, "PDA crc failed:" "calc_crc=0x%04x," "pdr_crc=0x%04x.\n", crc, pdacrc); pdaok = 0; } } else { WLAN_LOG_DEBUG(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_DEBUG(3, "pdrlen for address #%d " "at %#x:%#x:%d\n", i, pdaloc[i].cardaddr, pdaloc[i].auxctl, pdrlen); WLAN_LOG_DEBUG(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_DEBUG(3, "Didn't find PDA_END in buffer, " "trying next location.\n"); pdaok = 0; break; } } } if ( pdaok ) { WLAN_LOG_INFO( "PDA Read from 0x%08x 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_DEBUG(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_DEBUG(1,"Can't download with a port enabled.\n"); result = -EINVAL; goto done; } } /* Check that we're not already in a download state */ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { WLAN_LOG_DEBUG(1,"Download state not disabled.\n"); result = -EINVAL; goto done; } /* Are we supposed to go into genesis mode? */ if (exeaddr == 0x3f0000) { UINT16 initseq[2] = { 0xe100, 0xffa1 }; UINT16 readbuf[2]; UINT8 hcr = 0x0f; /* Default to x16 SRAM */ hw->isram16 = 1; WLAN_LOG_DEBUG(1, "Dropping into Genesis mode\n"); /* Issue card reset and enable aux port */ hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, 0); hfa384x_cmd_aux_enable(hw, 1); /* Genesis set */ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, initseq, sizeof(initseq)); hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, hcr); /* Validate memory config */ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, initseq, sizeof(initseq)); hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, readbuf, sizeof(initseq)); WLAN_HEX_DUMP(3, "readback", readbuf, sizeof(readbuf)); if (memcmp(initseq, readbuf, sizeof(readbuf))) { hcr = 0x1f; /* x8 SRAM */ hw->isram16 = 0; hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, initseq, sizeof(initseq)); hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, hcr); hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, initseq, sizeof(initseq)); hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, readbuf, sizeof(initseq)); WLAN_HEX_DUMP(2, "readback", readbuf, sizeof(readbuf)); if (memcmp(initseq, readbuf, sizeof(readbuf))) { WLAN_LOG_ERROR("Genesis mode failed\n"); result = -1; goto done; } } /* Now we're in genesis mode */ hw->dlstate = HFA384x_DLSTATE_GENESIS; goto done; } /* Retrieve the buffer loc&size and timeout */ if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, &(hw->bufinfo), sizeof(hw->bufinfo))) ) { goto done; } 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))) ) { goto done; } hw->dltimeout = hfa384x2host_16(hw->dltimeout); /* Enable the aux port */ if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { WLAN_LOG_DEBUG(1,"Aux enable failed, result=%d.\n", result); goto done; } /* 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); if ( result == 0) { /* Set the download state */ hw->dlstate = HFA384x_DLSTATE_RAMENABLED; } else { WLAN_LOG_DEBUG(1,"cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", lowaddr,hiaddr, result); /* Disable the aux port */ hfa384x_cmd_aux_disable(hw); } done: DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_ramdl_disable** Ends the ram download state.** Arguments:* hw device structure** 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_disable(hfa384x_t *hw){ DBFENTER; /* Check that we're already in the download state */ if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { return -EINVAL; } if (hw->dlstate == HFA384x_DLSTATE_GENESIS) { hfa384x_corereset(hw, prism2_reset_holdtime, prism2_reset_settletime, hw->isram16 ? 0x07: 0x17); goto done; } /* Disable the aux port */ hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); done: hw->dlstate = HFA384x_DLSTATE_DISABLED; hfa384x_cmd_aux_disable(hw); DBFEXIT; return 0;}/*----------------------------------------------------------------* hfa384x_drvr_ramdl_write** Performs a RAM download of a chunk of data. First checks to see* that we're in the RAM download state, then uses the aux functions* to 1) copy the data, 2) readback and compare. The download* state is unaffected. When all data has been written using* this function, call drvr_ramdl_disable() to end the download state* and restart the MAC.** Arguments:* hw device structure* daddr Card address to write to. (host order)* buf Ptr to data to write.* len Length of data (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_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len){ int result = 0; UINT8 *verbuf; DBFENTER; /* Check that we're in the ram download state */ if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { return -EINVAL; } WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr);#if 0WLAN_HEX_DUMP(1, "dldata", buf, len);#endif /* Copy the data via the aux port */ hfa384x_copy_to_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, buf, len); /* Create a buffer for the verify */ verbuf = kmalloc(len, GFP_KERNEL); if (verbuf == NULL ) return 1; /* Read back and compare */ hfa384x_copy_from_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, verbuf, len); if ( memcmp(buf, verbuf, len) ) { WLAN_LOG_DEBUG(1,"ramdl verify failed!\n"); result = -EINVAL; } kfree_s(verbuf, len); DBFEXIT; return result;}/*----------------------------------------------------------------* hfa384x_drvr_flashdl_enable** Begins the flash 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 retrieves the flash download* buffer location, buffer size, and timeout length.** Arguments:* hw device structure** 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_flashdl_enable(hfa384x_t *hw){ int result = 0; 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_DEBUG(1,"called when port enabled.\n"); return -EINVAL; } } /* Check that we're not already in a download state */ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { return -EINVAL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -