| 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" |
| 37 | typedef 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 | |
| 52 | typedef 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 */ |
| 67 | typedef 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 | |
| 72 | typedef 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 | |
| 92 | A_STATUS DevSetup(AR6K_DEVICE *pDev); |
| 93 | A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev); |
| 94 | A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev); |
| 95 | A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, |
| 96 | A_UINT32 *pLookAhead, |
| 97 | int TimeoutMS); |
| 98 | A_STATUS DevRWCompletionHandler(void *context, A_STATUS status); |
| 99 | A_STATUS DevDsrHandler(void *context); |
| 100 | A_STATUS DevCheckPendingRecvMsgsAsync(void *context); |
| 101 | void 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 |
| 108 | A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); |
| 109 | A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); |
| 110 | |
| 111 | static 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 | |
| 148 | static 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 |
| 188 | A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev); |
| 189 | #endif |
| 190 | |
| 191 | #endif /*AR6K_H_*/ |
| 192 | |