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