www.pudn.com > sdio-2.6.18-full.rar > bmi.c
/*
* Copyright (c) 2004-2006 Atheros Communications Inc.
* Wireless Network driver for Atheros AR6001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* This file contains the routines that implement the Boot loader messaging
* interface
*/
#include "../include/hif.h"
#include "../include/bmi.h"
#include "../include/htc.h"
#include "bmi_internal.h"
/*
Although we had envisioned BMI to run on top of HTC, this is not what the
final implementation boiled down to on dragon. Its a part of BSP and does
not use the HTC protocol either. On the host side, however, we were still
living with the original idea. I think the time has come to accept the truth
and separate it from HTC which has been carrying BMI's burden all this while.
It shall make HTC state machine relatively simpler
*/
/* ------ Static Variables ------ */
/* ------ Global Variable Declarations ------- */
A_BOOL bmiDone;
extern A_UINT32 debugbmi;
#ifdef DEBUG
#define AR_DEBUG_PRINTF(...) if (debugbmi) A_PRINTF(__VA_ARGS__);
#else
#define AR_DEBUG_PRINTF(...)
#endif
/* APIs visible to the driver */
void
BMIInit(void)
{
bmiDone = FALSE;
}
A_STATUS
BMIDone(HIF_DEVICE *device)
{
A_STATUS status;
A_UINT32 cid;
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Done: Enter (device: 0x%p)\n", device);
bmiDone = TRUE;
cid = BMI_DONE;
status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Done: Exit\n");
return A_OK;
}
A_STATUS
BMIGetTargetId(HIF_DEVICE *device, A_UINT32 *id)
{
A_STATUS status;
A_UINT32 cid;
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Get Target ID: Enter (device: 0x%p)\n", device);
cid = BMI_GET_TARGET_ID;
status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
status = bmiBufferReceive(device, (A_UCHAR *)id, sizeof(*id));
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to read from the device\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Get Target ID: Exit (ID: 0x%x)\n", *id);
return A_OK;
}
A_STATUS
BMIReadMemory(HIF_DEVICE *device,
A_UINT32 address,
A_UCHAR *buffer,
A_UINT32 length)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
A_UINT32 remaining, rxlen;
const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
A_UCHAR data[BMI_DATASZ_MAX + header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
device, address, length);
cid = BMI_READ_MEMORY;
remaining = length;
while (remaining)
{
rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
A_MEMCPY(&data[offset], &rxlen, sizeof(rxlen));
offset += sizeof(length);
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
status = bmiBufferReceive(device, data, rxlen);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to read from the device\n");
return A_ERROR;
}
A_MEMCPY(&buffer[length - remaining], data, rxlen);
remaining -= rxlen; address += rxlen;
}
AR_DEBUG_PRINTF("BMI Read Memory: Exit\n");
return A_OK;
}
A_STATUS
BMIWriteMemory(HIF_DEVICE *device,
A_UINT32 address,
A_UCHAR *buffer,
A_UINT32 length)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
A_UINT32 remaining, txlen;
const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
A_UCHAR data[BMI_DATASZ_MAX + header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
device, address, length);
cid = BMI_WRITE_MEMORY;
remaining = length;
while (remaining)
{
txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
remaining : (BMI_DATASZ_MAX - header);
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
A_MEMCPY(&data[offset], &txlen, sizeof(txlen));
offset += sizeof(txlen);
A_MEMCPY(&data[offset], &buffer[length - remaining], txlen);
offset += txlen;
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
remaining -= txlen; address += txlen;
}
AR_DEBUG_PRINTF("BMI Write Memory: Exit\n");
return A_OK;
}
A_STATUS
BMIExecute(HIF_DEVICE *device,
A_UINT32 address,
A_UINT32 *param)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(*param);
A_UCHAR data[header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
device, address, *param);
cid = BMI_EXECUTE;
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
A_MEMCPY(&data[offset], param, sizeof(*param));
offset += sizeof(*param);
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
status = bmiBufferReceive(device, data, sizeof(*param));
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to read from the device\n");
return A_ERROR;
}
A_MEMCPY(param, data, sizeof(*param));
AR_DEBUG_PRINTF("BMI Execute: Exit (param: %d)\n", *param);
return A_OK;
}
A_STATUS
BMISetAppStart(HIF_DEVICE *device,
A_UINT32 address)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
const A_UINT32 header = sizeof(cid) + sizeof(address);
A_UCHAR data[header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
device, address);
cid = BMI_SET_APP_START;
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Set App Start: Exit\n");
return A_OK;
}
A_STATUS
BMIReadSOCRegister(HIF_DEVICE *device,
A_UINT32 address,
A_UINT32 *param)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
const A_UINT32 header = sizeof(cid) + sizeof(address);
A_UCHAR data[header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
device, address);
cid = BMI_READ_SOC_REGISTER;
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
status = bmiBufferReceive(device, data, sizeof(*param));
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to read from the device\n");
return A_ERROR;
}
A_MEMCPY(param, data, sizeof(*param));
AR_DEBUG_PRINTF("BMI Read SOC Register: Exit (value: %d)\n", *param);
return A_OK;
}
A_STATUS
BMIWriteSOCRegister(HIF_DEVICE *device,
A_UINT32 address,
A_UINT32 param)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(param);
A_UCHAR data[header];
if (bmiDone) {
AR_DEBUG_PRINTF("Command disallowed\n");
return A_ERROR;
}
AR_DEBUG_PRINTF(
"BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
device, address, param);
cid = BMI_WRITE_SOC_REGISTER;
offset = 0;
A_MEMCPY(&data[offset], &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&data[offset], &address, sizeof(address));
offset += sizeof(address);
A_MEMCPY(&data[offset], ¶m, sizeof(param));
offset += sizeof(param);
status = bmiBufferSend(device, data, offset);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to write to the device\n");
return A_ERROR;
}
AR_DEBUG_PRINTF("BMI Read SOC Register: Exit\n");
return A_OK;
}
/* BMI Access routines */
A_STATUS
bmiBufferSend(HIF_DEVICE *device,
A_UCHAR *buffer,
A_UINT32 length)
{
A_STATUS status;
A_UINT32 timeout;
A_UINT32 address;
A_UCHAR cmdCredits;
HIF_REQUEST request;
A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
&mboxAddress, sizeof(mboxAddress));
cmdCredits = 0;
timeout = BMI_COMMUNICATION_TIMEOUT;
while(timeout-- && !cmdCredits) {
/* Read the counter register to get the command credits */
HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,
HIF_BYTE_BASIS, HIF_FIXED_ADDRESS);
address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
status = HIFReadWrite(device, address, &cmdCredits, 1,
&request, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to decrement the command credit count register\n");
return A_ERROR;
}
}
if (cmdCredits) {
HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO,
HIF_SYNCHRONOUS, HIF_BYTE_BASIS,
HIF_INCREMENTAL_ADDRESS);
address = mboxAddress[ENDPOINT1];
status = HIFReadWrite(device, address, buffer, length, &request, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to send the BMI data to the device\n");
return A_ERROR;
}
} else {
AR_DEBUG_PRINTF("BMI Communication timeout\n");
return A_ERROR;
}
return status;
}
A_STATUS
bmiBufferReceive(HIF_DEVICE *device,
A_UCHAR *buffer,
A_UINT32 length)
{
A_STATUS status;
A_UINT32 address;
A_UINT32 timeout;
A_UCHAR cmdCredits;
HIF_REQUEST request;
A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
&mboxAddress, sizeof(mboxAddress));
cmdCredits = 0;
timeout = BMI_COMMUNICATION_TIMEOUT;
while(timeout-- && !cmdCredits) {
/* Read the counter register to get the command credits */
HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,
HIF_BYTE_BASIS, HIF_FIXED_ADDRESS);
address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
status = HIFReadWrite(device, address, &cmdCredits, sizeof(cmdCredits),
&request, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to decrement the command credit count register\n");
return A_ERROR;
}
status = A_ERROR;
}
if (cmdCredits) {
HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO,
HIF_SYNCHRONOUS, HIF_BYTE_BASIS,
HIF_INCREMENTAL_ADDRESS);
address = mboxAddress[ENDPOINT1];
status = HIFReadWrite(device, address, buffer, length, &request, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF("Unable to read the BMI data from the device\n");
return A_ERROR;
}
} else {
AR_DEBUG_PRINTF("BMI Communication timeout\n");
return A_ERROR;
}
return status;
}