1296177Sjhibbits/******************************************************************************
2296177Sjhibbits
3296177Sjhibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4296177Sjhibbits All rights reserved.
5296177Sjhibbits
6296177Sjhibbits This is proprietary source code of Freescale Semiconductor Inc.,
7296177Sjhibbits and its use is subject to the NetComm Device Drivers EULA.
8296177Sjhibbits The copyright notice above does not evidence any actual or intended
9296177Sjhibbits publication of such source code.
10296177Sjhibbits
11296177Sjhibbits ALTERNATIVELY, redistribution and use in source and binary forms, with
12296177Sjhibbits or without modification, are permitted provided that the following
13296177Sjhibbits conditions are met:
14296177Sjhibbits     * Redistributions of source code must retain the above copyright
15296177Sjhibbits       notice, this list of conditions and the following disclaimer.
16296177Sjhibbits     * Redistributions in binary form must reproduce the above copyright
17296177Sjhibbits       notice, this list of conditions and the following disclaimer in the
18296177Sjhibbits       documentation and/or other materials provided with the distribution.
19296177Sjhibbits     * Neither the name of Freescale Semiconductor nor the
20296177Sjhibbits       names of its contributors may be used to endorse or promote products
21296177Sjhibbits       derived from this software without specific prior written permission.
22296177Sjhibbits
23296177Sjhibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24296177Sjhibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25296177Sjhibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26296177Sjhibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27296177Sjhibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28296177Sjhibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29296177Sjhibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30296177Sjhibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31296177Sjhibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32296177Sjhibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33296177Sjhibbits *
34296177Sjhibbits
35296177Sjhibbits **************************************************************************/
36296177Sjhibbits/******************************************************************************
37296177Sjhibbits @File          bman_low.c
38296177Sjhibbits
39296177Sjhibbits @Description   BM low-level implementation
40296177Sjhibbits*//***************************************************************************/
41296177Sjhibbits#include "std_ext.h"
42296177Sjhibbits#include "core_ext.h"
43296177Sjhibbits#include "xx_ext.h"
44296177Sjhibbits#include "error_ext.h"
45296177Sjhibbits
46296177Sjhibbits#include "bman_private.h"
47296177Sjhibbits
48296177Sjhibbits
49296177Sjhibbits/***************************/
50296177Sjhibbits/* Portal register assists */
51296177Sjhibbits/***************************/
52296177Sjhibbits
53296177Sjhibbits/* Cache-inhibited register offsets */
54296177Sjhibbits#define REG_RCR_PI_CINH     (void *)0x0000
55296177Sjhibbits#define REG_RCR_CI_CINH     (void *)0x0004
56296177Sjhibbits#define REG_RCR_ITR         (void *)0x0008
57296177Sjhibbits#define REG_CFG             (void *)0x0100
58296177Sjhibbits#define REG_SCN(n)          ((void *)(0x0200 + ((n) << 2)))
59296177Sjhibbits#define REG_ISR             (void *)0x0e00
60296177Sjhibbits#define REG_IER             (void *)0x0e04
61296177Sjhibbits#define REG_ISDR            (void *)0x0e08
62296177Sjhibbits#define REG_IIR             (void *)0x0e0c
63296177Sjhibbits
64296177Sjhibbits/* Cache-enabled register offsets */
65296177Sjhibbits#define CL_CR               (void *)0x0000
66296177Sjhibbits#define CL_RR0              (void *)0x0100
67296177Sjhibbits#define CL_RR1              (void *)0x0140
68296177Sjhibbits#define CL_RCR              (void *)0x1000
69296177Sjhibbits#define CL_RCR_PI_CENA      (void *)0x3000
70296177Sjhibbits#define CL_RCR_CI_CENA      (void *)0x3100
71296177Sjhibbits
72296177Sjhibbits/* The h/w design requires mappings to be size-aligned so that "add"s can be
73296177Sjhibbits * reduced to "or"s. The primitives below do the same for s/w. */
74296177Sjhibbits
75296177Sjhibbitsstatic __inline__ void *ptr_ADD(void *a, void *b)
76296177Sjhibbits{
77296177Sjhibbits    return (void *)((uintptr_t)a + (uintptr_t)b);
78296177Sjhibbits}
79296177Sjhibbits
80296177Sjhibbits/* Bitwise-OR two pointers */
81296177Sjhibbitsstatic __inline__ void *ptr_OR(void *a, void *b)
82296177Sjhibbits{
83296177Sjhibbits    return (void *)((uintptr_t)a | (uintptr_t)b);
84296177Sjhibbits}
85296177Sjhibbits
86296177Sjhibbits/* Cache-inhibited register access */
87296177Sjhibbitsstatic __inline__ uint32_t __bm_in(struct bm_addr *bm, void *offset)
88296177Sjhibbits{
89296177Sjhibbits    uint32_t    *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset);
90296177Sjhibbits    return GET_UINT32(*tmp);
91296177Sjhibbits}
92296177Sjhibbitsstatic __inline__ void __bm_out(struct bm_addr *bm, void *offset, uint32_t val)
93296177Sjhibbits{
94296177Sjhibbits    uint32_t    *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset);
95296177Sjhibbits    WRITE_UINT32(*tmp, val);
96296177Sjhibbits}
97296177Sjhibbits#define bm_in(reg)        __bm_in(&portal->addr, REG_##reg)
98296177Sjhibbits#define bm_out(reg, val)    __bm_out(&portal->addr, REG_##reg, val)
99296177Sjhibbits
100296177Sjhibbits/* Convert 'n' cachelines to a pointer value for bitwise OR */
101296177Sjhibbits#define bm_cl(n)        (void *)((n) << 6)
102296177Sjhibbits
103296177Sjhibbits/* Cache-enabled (index) register access */
104296177Sjhibbitsstatic __inline__ void __bm_cl_touch_ro(struct bm_addr *bm, void *offset)
105296177Sjhibbits{
106296177Sjhibbits    dcbt_ro(ptr_ADD(bm->addr_ce, offset));
107296177Sjhibbits}
108296177Sjhibbitsstatic __inline__ void __bm_cl_touch_rw(struct bm_addr *bm, void *offset)
109296177Sjhibbits{
110296177Sjhibbits    dcbt_rw(ptr_ADD(bm->addr_ce, offset));
111296177Sjhibbits}
112296177Sjhibbitsstatic __inline__ uint32_t __bm_cl_in(struct bm_addr *bm, void *offset)
113296177Sjhibbits{
114296177Sjhibbits    uint32_t    *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset);
115296177Sjhibbits    return GET_UINT32(*tmp);
116296177Sjhibbits}
117296177Sjhibbitsstatic __inline__ void __bm_cl_out(struct bm_addr *bm, void *offset, uint32_t val)
118296177Sjhibbits{
119296177Sjhibbits    uint32_t    *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset);
120296177Sjhibbits    WRITE_UINT32(*tmp, val);
121296177Sjhibbits    dcbf(tmp);
122296177Sjhibbits}
123296177Sjhibbitsstatic __inline__ void __bm_cl_invalidate(struct bm_addr *bm, void *offset)
124296177Sjhibbits{
125296177Sjhibbits    dcbi(ptr_ADD(bm->addr_ce, offset));
126296177Sjhibbits}
127296177Sjhibbits#define bm_cl_touch_ro(reg)    __bm_cl_touch_ro(&portal->addr, CL_##reg##_CENA)
128296177Sjhibbits#define bm_cl_touch_rw(reg)    __bm_cl_touch_rw(&portal->addr, CL_##reg##_CENA)
129296177Sjhibbits#define bm_cl_in(reg)        __bm_cl_in(&portal->addr, CL_##reg##_CENA)
130296177Sjhibbits#define bm_cl_out(reg, val)    __bm_cl_out(&portal->addr, CL_##reg##_CENA, val)
131296177Sjhibbits#define bm_cl_invalidate(reg) __bm_cl_invalidate(&portal->addr, CL_##reg##_CENA)
132296177Sjhibbits
133296177Sjhibbits/* Cyclic helper for rings. TODO: once we are able to do fine-grain perf
134296177Sjhibbits * analysis, look at using the "extra" bit in the ring index registers to avoid
135296177Sjhibbits * cyclic issues. */
136296177Sjhibbitsstatic __inline__ uint8_t cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last)
137296177Sjhibbits{
138296177Sjhibbits    /* 'first' is included, 'last' is excluded */
139296177Sjhibbits    if (first <= last)
140296177Sjhibbits        return (uint8_t)(last - first);
141296177Sjhibbits    return (uint8_t)(ringsize + last - first);
142296177Sjhibbits}
143296177Sjhibbits
144296177Sjhibbits/* --------------- */
145296177Sjhibbits/* --- RCR API --- */
146296177Sjhibbits
147296177Sjhibbits/* It's safer to code in terms of the 'rcr' object than the 'portal' object,
148296177Sjhibbits * because the latter runs the risk of copy-n-paste errors from other code where
149296177Sjhibbits * we could manipulate some other structure within 'portal'. */
150296177Sjhibbits/* #define RCR_API_START()      register struct bm_rcr *rcr = &portal->rcr */
151296177Sjhibbits
152296177Sjhibbits/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */
153296177Sjhibbits#define RCR_CARRYCLEAR(p) \
154296177Sjhibbits    (void *)((uintptr_t)(p) & (~(uintptr_t)(BM_RCR_SIZE << 6)))
155296177Sjhibbits
156296177Sjhibbits/* Bit-wise logic to convert a ring pointer to a ring index */
157296177Sjhibbitsstatic __inline__ uint8_t RCR_PTR2IDX(struct bm_rcr_entry *e)
158296177Sjhibbits{
159296177Sjhibbits    return (uint8_t)(((uint32_t)e >> 6) & (BM_RCR_SIZE - 1));
160296177Sjhibbits}
161296177Sjhibbits
162296177Sjhibbits/* Increment the 'cursor' ring pointer, taking 'vbit' into account */
163296177Sjhibbitsstatic __inline__ void RCR_INC(struct bm_rcr *rcr)
164296177Sjhibbits{
165296177Sjhibbits    /* NB: this is odd-looking, but experiments show that it generates
166296177Sjhibbits     * fast code with essentially no branching overheads. We increment to
167296177Sjhibbits     * the next RCR pointer and handle overflow and 'vbit'. */
168296177Sjhibbits    struct bm_rcr_entry *partial = rcr->cursor + 1;
169296177Sjhibbits    rcr->cursor = RCR_CARRYCLEAR(partial);
170296177Sjhibbits    if (partial != rcr->cursor)
171296177Sjhibbits        rcr->vbit ^= BM_RCR_VERB_VBIT;
172296177Sjhibbits}
173296177Sjhibbits
174296177Sjhibbitst_Error bm_rcr_init(struct bm_portal *portal,
175296177Sjhibbits                    e_BmPortalProduceMode pmode,
176296177Sjhibbits                    e_BmPortalRcrConsumeMode cmode)
177296177Sjhibbits{
178296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
179296177Sjhibbits    uint32_t cfg;
180296177Sjhibbits    uint8_t pi;
181296177Sjhibbits
182296177Sjhibbits    rcr->ring = ptr_ADD(portal->addr.addr_ce, CL_RCR);
183296177Sjhibbits    rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
184296177Sjhibbits    pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1));
185296177Sjhibbits    rcr->cursor = rcr->ring + pi;
186296177Sjhibbits    rcr->vbit = (uint8_t)((bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ?  BM_RCR_VERB_VBIT : 0);
187296177Sjhibbits    rcr->available = (uint8_t)(BM_RCR_SIZE - 1 - cyc_diff(BM_RCR_SIZE, rcr->ci, pi));
188296177Sjhibbits    rcr->ithresh = (uint8_t)bm_in(RCR_ITR);
189296177Sjhibbits#ifdef BM_CHECKING
190296177Sjhibbits    rcr->busy = 0;
191296177Sjhibbits    rcr->pmode = pmode;
192296177Sjhibbits    rcr->cmode = cmode;
193296177Sjhibbits#else
194296177Sjhibbits    UNUSED(cmode);
195296177Sjhibbits#endif /* BM_CHECKING */
196296177Sjhibbits    cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */
197296177Sjhibbits    bm_out(CFG, cfg);
198296177Sjhibbits    return 0;
199296177Sjhibbits}
200296177Sjhibbits
201296177Sjhibbitsvoid bm_rcr_finish(struct bm_portal *portal)
202296177Sjhibbits{
203296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
204296177Sjhibbits    uint8_t pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1));
205296177Sjhibbits    uint8_t ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
206296177Sjhibbits    ASSERT_COND(!rcr->busy);
207296177Sjhibbits    if (pi != RCR_PTR2IDX(rcr->cursor))
208296177Sjhibbits        REPORT_ERROR(WARNING, E_INVALID_STATE, ("losing uncommitted RCR entries"));
209296177Sjhibbits    if (ci != rcr->ci)
210296177Sjhibbits        REPORT_ERROR(WARNING, E_INVALID_STATE, ("missing existing RCR completions"));
211296177Sjhibbits    if (rcr->ci != RCR_PTR2IDX(rcr->cursor))
212296177Sjhibbits        REPORT_ERROR(WARNING, E_INVALID_STATE, ("RCR destroyed unquiesced"));
213296177Sjhibbits}
214296177Sjhibbits
215296177Sjhibbitsstruct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal)
216296177Sjhibbits{
217296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
218296177Sjhibbits    ASSERT_COND(!rcr->busy);
219296177Sjhibbits    if (!rcr->available)
220296177Sjhibbits        return NULL;
221296177Sjhibbits#ifdef BM_CHECKING
222296177Sjhibbits    rcr->busy = 1;
223296177Sjhibbits#endif /* BM_CHECKING */
224296177Sjhibbits    dcbz_64(rcr->cursor);
225296177Sjhibbits    return rcr->cursor;
226296177Sjhibbits}
227296177Sjhibbits
228296177Sjhibbitsvoid bm_rcr_abort(struct bm_portal *portal)
229296177Sjhibbits{
230296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
231296177Sjhibbits    ASSERT_COND(rcr->busy);
232296177Sjhibbits#ifdef BM_CHECKING
233296177Sjhibbits    rcr->busy = 0;
234296177Sjhibbits#else
235296177Sjhibbits    UNUSED(rcr);
236296177Sjhibbits#endif /* BM_CHECKING */
237296177Sjhibbits}
238296177Sjhibbits
239296177Sjhibbitsstruct bm_rcr_entry *bm_rcr_pend_and_next(struct bm_portal *portal, uint8_t myverb)
240296177Sjhibbits{
241296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
242296177Sjhibbits    ASSERT_COND(rcr->busy);
243296177Sjhibbits    ASSERT_COND(rcr->pmode != e_BmPortalPVB);
244296177Sjhibbits    if (rcr->available == 1)
245296177Sjhibbits        return NULL;
246296177Sjhibbits    rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
247296177Sjhibbits    dcbf_64(rcr->cursor);
248296177Sjhibbits    RCR_INC(rcr);
249296177Sjhibbits    rcr->available--;
250296177Sjhibbits    dcbz_64(rcr->cursor);
251296177Sjhibbits    return rcr->cursor;
252296177Sjhibbits}
253296177Sjhibbits
254296177Sjhibbitsvoid bm_rcr_pci_commit(struct bm_portal *portal, uint8_t myverb)
255296177Sjhibbits{
256296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
257296177Sjhibbits    ASSERT_COND(rcr->busy);
258296177Sjhibbits    ASSERT_COND(rcr->pmode == e_BmPortalPCI);
259296177Sjhibbits    rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
260296177Sjhibbits    RCR_INC(rcr);
261296177Sjhibbits    rcr->available--;
262296177Sjhibbits    hwsync();
263296177Sjhibbits    bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor));
264296177Sjhibbits#ifdef BM_CHECKING
265296177Sjhibbits    rcr->busy = 0;
266296177Sjhibbits#endif /* BM_CHECKING */
267296177Sjhibbits}
268296177Sjhibbits
269296177Sjhibbitsvoid bm_rcr_pce_prefetch(struct bm_portal *portal)
270296177Sjhibbits{
271296177Sjhibbits    ASSERT_COND(((struct bm_rcr *)&portal->rcr)->pmode == e_BmPortalPCE);
272296177Sjhibbits    bm_cl_invalidate(RCR_PI);
273296177Sjhibbits    bm_cl_touch_rw(RCR_PI);
274296177Sjhibbits}
275296177Sjhibbits
276296177Sjhibbitsvoid bm_rcr_pce_commit(struct bm_portal *portal, uint8_t myverb)
277296177Sjhibbits{
278296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
279296177Sjhibbits    ASSERT_COND(rcr->busy);
280296177Sjhibbits    ASSERT_COND(rcr->pmode == e_BmPortalPCE);
281296177Sjhibbits    rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
282296177Sjhibbits    RCR_INC(rcr);
283296177Sjhibbits    rcr->available--;
284296177Sjhibbits    lwsync();
285296177Sjhibbits    bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor));
286296177Sjhibbits#ifdef BM_CHECKING
287296177Sjhibbits    rcr->busy = 0;
288296177Sjhibbits#endif /* BM_CHECKING */
289296177Sjhibbits}
290296177Sjhibbits
291296177Sjhibbitsvoid bm_rcr_pvb_commit(struct bm_portal *portal, uint8_t myverb)
292296177Sjhibbits{
293296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
294296177Sjhibbits    struct bm_rcr_entry *rcursor;
295296177Sjhibbits    ASSERT_COND(rcr->busy);
296296177Sjhibbits    ASSERT_COND(rcr->pmode == e_BmPortalPVB);
297296177Sjhibbits    lwsync();
298296177Sjhibbits    rcursor = rcr->cursor;
299296177Sjhibbits    rcursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
300296177Sjhibbits    dcbf_64(rcursor);
301296177Sjhibbits    RCR_INC(rcr);
302296177Sjhibbits    rcr->available--;
303296177Sjhibbits#ifdef BM_CHECKING
304296177Sjhibbits    rcr->busy = 0;
305296177Sjhibbits#endif /* BM_CHECKING */
306296177Sjhibbits}
307296177Sjhibbits
308296177Sjhibbits
309296177Sjhibbitsuint8_t bm_rcr_cci_update(struct bm_portal *portal)
310296177Sjhibbits{
311296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
312296177Sjhibbits    uint8_t diff, old_ci = rcr->ci;
313296177Sjhibbits    ASSERT_COND(rcr->cmode == e_BmPortalRcrCCI);
314296177Sjhibbits    rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
315296177Sjhibbits    diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
316296177Sjhibbits    rcr->available += diff;
317296177Sjhibbits    return diff;
318296177Sjhibbits}
319296177Sjhibbits
320296177Sjhibbits
321296177Sjhibbitsvoid bm_rcr_cce_prefetch(struct bm_portal *portal)
322296177Sjhibbits{
323296177Sjhibbits    ASSERT_COND(((struct bm_rcr *)&portal->rcr)->cmode == e_BmPortalRcrCCE);
324296177Sjhibbits    bm_cl_touch_ro(RCR_CI);
325296177Sjhibbits}
326296177Sjhibbits
327296177Sjhibbits
328296177Sjhibbitsuint8_t bm_rcr_cce_update(struct bm_portal *portal)
329296177Sjhibbits{
330296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
331296177Sjhibbits    uint8_t diff, old_ci = rcr->ci;
332296177Sjhibbits    ASSERT_COND(rcr->cmode == e_BmPortalRcrCCE);
333296177Sjhibbits    rcr->ci = (uint8_t)(bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1));
334296177Sjhibbits    bm_cl_invalidate(RCR_CI);
335296177Sjhibbits    diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
336296177Sjhibbits    rcr->available += diff;
337296177Sjhibbits    return diff;
338296177Sjhibbits}
339296177Sjhibbits
340296177Sjhibbits
341296177Sjhibbitsuint8_t bm_rcr_get_ithresh(struct bm_portal *portal)
342296177Sjhibbits{
343296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
344296177Sjhibbits    return rcr->ithresh;
345296177Sjhibbits}
346296177Sjhibbits
347296177Sjhibbits
348296177Sjhibbitsvoid bm_rcr_set_ithresh(struct bm_portal *portal, uint8_t ithresh)
349296177Sjhibbits{
350296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
351296177Sjhibbits    rcr->ithresh = ithresh;
352296177Sjhibbits    bm_out(RCR_ITR, ithresh);
353296177Sjhibbits}
354296177Sjhibbits
355296177Sjhibbits
356296177Sjhibbitsuint8_t bm_rcr_get_avail(struct bm_portal *portal)
357296177Sjhibbits{
358296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
359296177Sjhibbits    return rcr->available;
360296177Sjhibbits}
361296177Sjhibbits
362296177Sjhibbits
363296177Sjhibbitsuint8_t bm_rcr_get_fill(struct bm_portal *portal)
364296177Sjhibbits{
365296177Sjhibbits    register struct bm_rcr *rcr = &portal->rcr;
366296177Sjhibbits    return (uint8_t)(BM_RCR_SIZE - 1 - rcr->available);
367296177Sjhibbits}
368296177Sjhibbits
369296177Sjhibbits
370296177Sjhibbits/* ------------------------------ */
371296177Sjhibbits/* --- Management command API --- */
372296177Sjhibbits
373296177Sjhibbits/* It's safer to code in terms of the 'mc' object than the 'portal' object,
374296177Sjhibbits * because the latter runs the risk of copy-n-paste errors from other code where
375296177Sjhibbits * we could manipulate some other structure within 'portal'. */
376296177Sjhibbits/* #define MC_API_START()      register struct bm_mc *mc = &portal->mc */
377296177Sjhibbits
378296177Sjhibbits
379296177Sjhibbitst_Error bm_mc_init(struct bm_portal *portal)
380296177Sjhibbits{
381296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
382296177Sjhibbits    mc->cr = ptr_ADD(portal->addr.addr_ce, CL_CR);
383296177Sjhibbits    mc->rr = ptr_ADD(portal->addr.addr_ce, CL_RR0);
384296177Sjhibbits    mc->rridx = (uint8_t)((mc->cr->__dont_write_directly__verb & BM_MCC_VERB_VBIT) ?
385296177Sjhibbits            0 : 1);
386296177Sjhibbits    mc->vbit = (uint8_t)(mc->rridx ? BM_MCC_VERB_VBIT : 0);
387296177Sjhibbits#ifdef BM_CHECKING
388296177Sjhibbits    mc->state = mc_idle;
389296177Sjhibbits#endif /* BM_CHECKING */
390296177Sjhibbits    return 0;
391296177Sjhibbits}
392296177Sjhibbits
393296177Sjhibbits
394296177Sjhibbitsvoid bm_mc_finish(struct bm_portal *portal)
395296177Sjhibbits{
396296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
397296177Sjhibbits    ASSERT_COND(mc->state == mc_idle);
398296177Sjhibbits#ifdef BM_CHECKING
399296177Sjhibbits    if (mc->state != mc_idle)
400296177Sjhibbits        REPORT_ERROR(WARNING, E_INVALID_STATE, ("Losing incomplete MC command"));
401296177Sjhibbits#else
402296177Sjhibbits    UNUSED(mc);
403296177Sjhibbits#endif /* BM_CHECKING */
404296177Sjhibbits}
405296177Sjhibbits
406296177Sjhibbits
407296177Sjhibbitsstruct bm_mc_command *bm_mc_start(struct bm_portal *portal)
408296177Sjhibbits{
409296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
410296177Sjhibbits    ASSERT_COND(mc->state == mc_idle);
411296177Sjhibbits#ifdef BM_CHECKING
412296177Sjhibbits    mc->state = mc_user;
413296177Sjhibbits#endif /* BM_CHECKING */
414296177Sjhibbits    dcbz_64(mc->cr);
415296177Sjhibbits    return mc->cr;
416296177Sjhibbits}
417296177Sjhibbits
418296177Sjhibbits
419296177Sjhibbitsvoid bm_mc_abort(struct bm_portal *portal)
420296177Sjhibbits{
421296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
422296177Sjhibbits    ASSERT_COND(mc->state == mc_user);
423296177Sjhibbits#ifdef BM_CHECKING
424296177Sjhibbits    mc->state = mc_idle;
425296177Sjhibbits#else
426296177Sjhibbits    UNUSED(mc);
427296177Sjhibbits#endif /* BM_CHECKING */
428296177Sjhibbits}
429296177Sjhibbits
430296177Sjhibbits
431296177Sjhibbitsvoid bm_mc_commit(struct bm_portal *portal, uint8_t myverb)
432296177Sjhibbits{
433296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
434296177Sjhibbits    ASSERT_COND(mc->state == mc_user);
435296177Sjhibbits    lwsync();
436296177Sjhibbits    mc->cr->__dont_write_directly__verb = (uint8_t)(myverb | mc->vbit);
437296177Sjhibbits    dcbf_64(mc->cr);
438296177Sjhibbits    dcbit_ro(mc->rr + mc->rridx);
439296177Sjhibbits#ifdef BM_CHECKING
440296177Sjhibbits    mc->state = mc_hw;
441296177Sjhibbits#endif /* BM_CHECKING */
442296177Sjhibbits}
443296177Sjhibbits
444296177Sjhibbits
445296177Sjhibbitsstruct bm_mc_result *bm_mc_result(struct bm_portal *portal)
446296177Sjhibbits{
447296177Sjhibbits    register struct bm_mc *mc = &portal->mc;
448296177Sjhibbits    struct bm_mc_result *rr = mc->rr + mc->rridx;
449296177Sjhibbits    ASSERT_COND(mc->state == mc_hw);
450296177Sjhibbits    /* The inactive response register's verb byte always returns zero until
451296177Sjhibbits     * its command is submitted and completed. This includes the valid-bit,
452296177Sjhibbits     * in case you were wondering... */
453296177Sjhibbits    if (!rr->verb) {
454296177Sjhibbits        dcbit_ro(rr);
455296177Sjhibbits        return NULL;
456296177Sjhibbits    }
457296177Sjhibbits    mc->rridx ^= 1;
458296177Sjhibbits    mc->vbit ^= BM_MCC_VERB_VBIT;
459296177Sjhibbits#ifdef BM_CHECKING
460296177Sjhibbits    mc->state = mc_idle;
461296177Sjhibbits#endif /* BM_CHECKING */
462296177Sjhibbits    return rr;
463296177Sjhibbits}
464296177Sjhibbits
465296177Sjhibbits/* ------------------------------------- */
466296177Sjhibbits/* --- Portal interrupt register API --- */
467296177Sjhibbits
468296177Sjhibbits#define SCN_REG(bpid) REG_SCN((bpid) / 32)
469296177Sjhibbits#define SCN_BIT(bpid) (0x80000000 >> (bpid & 31))
470296177Sjhibbitsvoid bm_isr_bscn_mask(struct bm_portal *portal, uint8_t bpid, int enable)
471296177Sjhibbits{
472296177Sjhibbits    uint32_t val;
473296177Sjhibbits    ASSERT_COND(bpid < BM_MAX_NUM_OF_POOLS);
474296177Sjhibbits    /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */
475296177Sjhibbits    val = __bm_in(&portal->addr, SCN_REG(bpid));
476296177Sjhibbits    if (enable)
477296177Sjhibbits        val |= SCN_BIT(bpid);
478296177Sjhibbits    else
479296177Sjhibbits        val &= ~SCN_BIT(bpid);
480296177Sjhibbits    __bm_out(&portal->addr, SCN_REG(bpid), val);
481296177Sjhibbits}
482296177Sjhibbits
483296177Sjhibbits
484296177Sjhibbitsuint32_t __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n)
485296177Sjhibbits{
486296177Sjhibbits    return __bm_in(&portal->addr, PTR_MOVE(REG_ISR, (n << 2)));
487296177Sjhibbits}
488296177Sjhibbits
489296177Sjhibbits
490296177Sjhibbitsvoid __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, uint32_t val)
491296177Sjhibbits{
492296177Sjhibbits    __bm_out(&portal->addr, PTR_MOVE(REG_ISR, (n << 2)), val);
493296177Sjhibbits}
494296177Sjhibbits
495