1/* 2 * 3 * Copyright (c) 2007 Atheros Communications Inc. 4 * All rights reserved. 5 * 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation; 10 * 11 * Software distributed under the License is distributed on an "AS 12 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 13 * implied. See the License for the specific language governing 14 * rights and limitations under the License. 15 * 16 * 17 * 18 */ 19 20#ifndef AR6K_H_ 21#define AR6K_H_ 22 23#define AR6K_MAILBOXES 4 24 25/* HTC runs over mailbox 0 */ 26#define HTC_MAILBOX 0 27 28#define AR6K_TARGET_DEBUG_INTR_MASK 0x01 29 30#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ 31 INT_STATUS_ENABLE_CPU_MASK | \ 32 INT_STATUS_ENABLE_COUNTER_MASK) 33 34//#define MBOXHW_UNIT_TEST 1 35 36#include "athstartpack.h" 37typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS { 38 A_UINT8 host_int_status; 39 A_UINT8 cpu_int_status; 40 A_UINT8 error_int_status; 41 A_UINT8 counter_int_status; 42 A_UINT8 mbox_frame; 43 A_UINT8 rx_lookahead_valid; 44 A_UINT8 hole[2]; 45 A_UINT32 rx_lookahead[2]; 46} POSTPACK AR6K_IRQ_PROC_REGISTERS; 47 48#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS) 49 50 51 52typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS { 53 A_UINT8 int_status_enable; 54 A_UINT8 cpu_int_status_enable; 55 A_UINT8 error_status_enable; 56 A_UINT8 counter_int_status_enable; 57} POSTPACK AR6K_IRQ_ENABLE_REGISTERS; 58 59#include "athendpack.h" 60 61#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS) 62 63#define AR6K_REG_IO_BUFFER_SIZE 32 64#define AR6K_MAX_REG_IO_BUFFERS 8 65 66/* buffers for ASYNC I/O */ 67typedef struct AR6K_ASYNC_REG_IO_BUFFER { 68 HTC_PACKET HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */ 69 A_UINT8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; 70} AR6K_ASYNC_REG_IO_BUFFER; 71 72typedef struct _AR6K_DEVICE { 73 A_MUTEX_T Lock; 74 AR6K_IRQ_PROC_REGISTERS IrqProcRegisters; 75 AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters; 76 void *HIFDevice; 77 A_UINT32 BlockSize; 78 A_UINT32 BlockMask; 79 A_UINT32 MailboxAddress; 80 HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc; 81 void *HTCContext; 82 HTC_PACKET_QUEUE RegisterIOList; 83 AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS]; 84 void (*TargetFailureCallback)(void *Context); 85 A_STATUS (*MessagePendingCallback)(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc); 86 HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; 87 HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; 88} AR6K_DEVICE; 89 90#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY) 91 92A_STATUS DevSetup(AR6K_DEVICE *pDev); 93A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev); 94A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev); 95A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, 96 A_UINT32 *pLookAhead, 97 int TimeoutMS); 98A_STATUS DevRWCompletionHandler(void *context, A_STATUS status); 99A_STATUS DevDsrHandler(void *context); 100A_STATUS DevCheckPendingRecvMsgsAsync(void *context); 101void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs, 102 AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs); 103 104#define DEV_STOP_RECV_ASYNC TRUE 105#define DEV_STOP_RECV_SYNC FALSE 106#define DEV_ENABLE_RECV_ASYNC TRUE 107#define DEV_ENABLE_RECV_SYNC FALSE 108A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); 109A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); 110 111static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) { 112 A_UINT32 paddedLength; 113 A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; 114 A_STATUS status; 115 116 /* adjust the length to be a multiple of block size if appropriate */ 117 paddedLength = (SendLength + (pDev->BlockMask)) & 118 (~(pDev->BlockMask)); 119#if 0 // BufferLength may not be set in , fix this... 120 if (paddedLength > pPacket->BufferLength) { 121 AR_DEBUG_ASSERT(FALSE); 122 if (pPacket->Completion != NULL) { 123 COMPLETE_HTC_PACKET(pPacket,A_EINVAL); 124 } 125 return A_EINVAL; 126 } 127#endif 128 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 129 ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", 130 paddedLength, 131 pDev->MailboxAddress, 132 sync ? "SYNC" : "ASYNC")); 133 134 status = HIFReadWrite(pDev->HIFDevice, 135 pDev->MailboxAddress, 136 pPacket->pBuffer, 137 paddedLength, /* the padded length */ 138 sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, 139 sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ 140 141 if (sync) { 142 pPacket->Status = status; 143 } 144 145 return status; 146} 147 148static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) { 149 A_UINT32 paddedLength; 150 A_STATUS status; 151 A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; 152 153 /* adjust the length to be a multiple of block size if appropriate */ 154 paddedLength = (RecvLength + (pDev->BlockMask)) & 155 (~(pDev->BlockMask)); 156 if (paddedLength > pPacket->BufferLength) { 157 AR_DEBUG_ASSERT(FALSE); 158 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 159 ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", 160 paddedLength,RecvLength,pPacket->BufferLength)); 161 if (pPacket->Completion != NULL) { 162 COMPLETE_HTC_PACKET(pPacket,A_EINVAL); 163 } 164 return A_EINVAL; 165 } 166 167 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 168 ("DevRecvPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", 169 paddedLength, 170 pDev->MailboxAddress, 171 sync ? "SYNC" : "ASYNC")); 172 173 status = HIFReadWrite(pDev->HIFDevice, 174 pDev->MailboxAddress, 175 pPacket->pBuffer, 176 paddedLength, 177 sync ? HIF_RD_SYNC_BLOCK_INC : HIF_RD_ASYNC_BLOCK_INC, 178 sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ 179 180 if (sync) { 181 pPacket->Status = status; 182 } 183 184 return status; 185} 186 187#ifdef MBOXHW_UNIT_TEST 188A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev); 189#endif 190 191#endif /*AR6K_H_*/ 192