1  /**********************************************************************
2  * Copyright (C) 2014-2015 Cadence Design Systems, Inc.- http://www.cadence.com
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  ******************************************************************************
17  * edd_rx.c
18  * Ethernet DMA MAC Driver
19  *
20  * Rx-related functions source file
21  *****************************************************************************/
22 /****************************************************************************
23 * Modification by Infineon: To make this file compile with ModusToolbox
24 * toolchain
25 *****************************************************************************/
26 
27 #include "cy_device.h"
28 
29 #if defined (CY_IP_MXETH)
30 
31 #include "cdn_stdint.h"
32 #include "cdn_errno.h"
33 #include "log.h"
34 #include "cps_v2.h"
35 #include "emac_regs.h"
36 #include "cedi.h"
37 #include "edd_int.h"
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 /******************************************************************************
43  * Driver API functions
44  *****************************************************************************/
45 
46 /* Identify max Rx pkt size for queues - determined by size of Rx packet buffer
47  * (if using full store & forward mode), and the current maximum frame size,
48  * e.g. 1518, 1536 or jumbo frame.
49  * @param pD - driver private state info specific to this instance
50  * @param maxSize - pointer for returning max frame size, same for each Rx queue
51  * @return 0 if successful
52  * @return EINVAL if invalid parameters
53  */
emacCalcMaxRxFrameSize(void * pD,uint32_t * maxSize)54 uint32_t emacCalcMaxRxFrameSize(void *pD, uint32_t *maxSize) {
55     uint16_t ram_word_size, ram_addr_bits;
56     uint32_t ram_size, max_size, tmp;
57     uint8_t enabled = 0;
58     uint16_t length;
59 
60     if ((pD==NULL) || (maxSize==NULL)) return EINVAL;
61 
62     if (0!=emacGetJumboFramesRx(pD,&enabled))
63         return EINVAL;
64 
65     if (enabled) {
66         if (0!=emacGetJumboFrameRxMaxLen(pD, &length))
67             return EINVAL;
68         max_size = length;
69     } else {
70         if (0!=emacGet1536ByteFramesRx(pD,&enabled))
71             return EINVAL;
72         if (enabled)
73             max_size = 1536;
74         else
75             max_size = 1518;
76     }
77 
78     if (0!=emacGetRxPartialStFwd(pD, &tmp, &enabled))
79         return EINVAL;
80 
81     if ((!enabled) && CEDI_PdVar(hwCfg).rx_pkt_buffer)
82     {
83         // What is word size of SRAM in bytes
84         ram_word_size = (CEDI_PdVar(hwCfg).rx_pbuf_data >> 1)+1;
85         //vDbgMsg(DBG_GEN_MSG, 10, "RAM word size = %u (x32 bits)\n", CEDI_PdVar(hwCfg).rx_pbuf_data);
86         ram_addr_bits = CEDI_PdVar(hwCfg).rx_pbuf_addr;
87         //vDbgMsg(DBG_GEN_MSG, 10, "RAM Rx addr bits = %u\n", ram_addr_bits);
88 
89         ram_size = (1<<(ram_addr_bits + ram_word_size + 1)) - 96;
90         vDbgMsg(DBG_GEN_MSG, 10, "RAM size = %u\n", ram_size);
91 
92         if (ram_size<max_size)
93             max_size = ram_size;
94     }
95     vDbgMsg(DBG_GEN_MSG, 10, "Max Rx frame size = %u\n", max_size);
96 
97     *maxSize = max_size;
98     return 0;
99 }
100 
101 /* Add a buffer (size determined by rxBufLength in CEDI_Config) to the end of
102  * the receive buffer queue.  This function is intended to be used during
103  * setting up the receive buffers, and should not be called while Rx is
104  * enabled or unread data remains in the queue.
105  * @param pD - driver private state info specific to this instance
106  * @param queueNum - number of the Rx queue (range 0 to rxQs-1)
107  * @param buf - pointer to struct for virtual and physical addresses of buffer.
108  *      Physical address checked for word-alignment in 64/128-bit width cases.
109  * @param init - if <>0 then initialise the buffer data to all zeros
110  * @return 0 if successful, EINVAL if invalid queueNum, buffer alignment, or
111  *    bufStart pointer/addresses
112  */
emacAddRxBuf(void * pD,uint8_t queueNum,CEDI_BuffAddr * buf,uint8_t init)113 uint32_t emacAddRxBuf(void *pD, uint8_t queueNum, CEDI_BuffAddr *buf, uint8_t init)
114 {
115     uint32_t tmp, bufLenWords;
116     rxQueue_t *rxQ;
117 
118     if (!pD) return EINVAL;
119 
120     if (queueNum>=(CEDI_PdVar(cfg)).rxQs) {
121         vDbgMsg(DBG_GEN_MSG, 5, "Error: Invalid Rx queue number: %u\n", queueNum);
122         return EINVAL;
123     }
124 
125     if ((buf==0) || (buf->vAddr==0) || (buf->pAddr==0)) {
126         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: NULL buf parameter");
127         return EINVAL;
128     }
129 //    vDbgMsg(DBG_GEN_MSG, 10, "%s entered (regBase %08X) bufV=0x%08X bufP=0x%08X\n", __func__,
130 //            CEDI_PdVar(cfg).regBase, buf->vAddr, buf->pAddr);
131 
132     rxQ = &(CEDI_PdVar(rxQueue[queueNum]));
133 
134     if (rxQ->numRxBufs>=((CEDI_PdVar(cfg)).rxQLen[queueNum])) {
135         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: Rx descriptor list full");
136         return EINVAL;
137     }
138 
139     /* alignment checking */
140     switch (CEDI_PdVar(cfg).dmaBusWidth) {
141     case CEDI_DMA_BUS_WIDTH_32:
142         tmp = 4; break;
143     case CEDI_DMA_BUS_WIDTH_64:
144         tmp = 8; break;
145     case CEDI_DMA_BUS_WIDTH_128:
146         tmp = 16; break;
147     default: tmp = 4; break;
148     }
149     if ((buf->pAddr)%tmp) {
150         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: Rx buffer not word-aligned");
151         return EINVAL;
152     }
153 
154     /* save virtual address */
155     *(rxQ->rxEndVA) = buf->vAddr;
156 
157     bufLenWords = (CEDI_PdVar(cfg).rxBufLength[queueNum])<<4;
158     if (init)
159         for (tmp=0; tmp<bufLenWords; tmp++)
160             CPS_UncachedWrite32((uint32_t *)(buf->vAddr)+tmp, 0);
161 
162     /* clear wrap & used on old end, add new buffer */
163     CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[0]),
164                             buf->pAddr & CEDI_RXD_ADDR_MASK);
165     /* upper 32 bits if 64 bit addressing */
166     if (CEDI_PdVar(cfg).dmaAddrBusWidth) {
167 #ifdef CEDI_64B_COMPILE
168         /* 64-bit addressing */
169         CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[2]),
170                              (buf->pAddr & 0xFFFFFFFF00000000)>>32);
171 #else
172         /* 32-bit addressing */
173         CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[2]), 0x00000000);
174 #endif
175     }
176 
177     /* put known pattern into word[1] for debugging */
178     CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[1]), CEDI_RXD_EMPTY);
179 
180     /* inc end & stop pointer */
181     rxQ->rxDescEnd = (rxDesc *)(((uintptr_t)rxQ->rxDescEnd) +
182             (CEDI_PdVar(rxDescriptorSize)));
183     rxQ->rxDescStop = rxQ->rxDescEnd;
184 
185     /* inc VA end & stop pointers & buffer count */
186     rxQ->rxEndVA++;
187     rxQ->rxStopVA++;
188     *(rxQ->rxStopVA) = 0;
189     rxQ->numRxBufs++;
190 
191     /* write new end(-stop) descriptor */
192     CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[0]),
193                              CEDI_RXD_WRAP | CEDI_RXD_USED );
194 
195     return 0;
196 }
197 
198 /* Get the number of useable buffers/descriptors present in the specified
199  * Rx queue, excluding the end-stop descriptor.
200  * @param pD - driver private state info specific to this instance
201  * @param queueNum - number of the Rx queue (range 0 to rxQs-1)
202  * @param numBufs - pointer for returning number of descriptors
203  * @return 0 if successful
204  * @return EINVAL if invalid parameter
205  */
emacNumRxBufs(void * pD,uint8_t queueNum,uint16_t * numBufs)206 uint32_t emacNumRxBufs(void *pD, uint8_t queueNum, uint16_t *numBufs)
207 {
208     if ((pD==NULL) || (numBufs==NULL) || (queueNum>=(CEDI_PdVar(cfg)).rxQs))
209         return EINVAL;
210 
211     *numBufs = (CEDI_PdVar(rxQueue[queueNum])).numRxBufs;
212     return 0;
213 }
214 
215 /* Get the number of buffers/descriptors marked "used" in the specified Rx
216  *   queue (excluding unuseable end-stop), i.e. those holding unread data.
217  * @param pD - driver private state info specific to this instance
218  * @param queueNum - number of the Rx queue (range 0 to rxQs-1)
219  * @return number of used buffers
220  * @return 0 if invalid parameter
221  */
emacNumRxUsed(void * pD,uint8_t queueNum)222 uint32_t emacNumRxUsed(void *pD, uint8_t queueNum)
223 {
224     uint32_t tmp, thisWd, count=0;
225     rxDesc *thisDesc;
226     rxQueue_t *rxQ;
227 
228     if ((pD==NULL) || (queueNum>=(CEDI_PdVar(cfg)).rxQs))
229         return 0;
230 
231     rxQ = &(CEDI_PdVar(rxQueue[queueNum]));
232     /* count forward from tail, until used not set */
233     thisDesc =  rxQ->rxDescTail;
234     for (tmp = 0; tmp<rxQ->numRxBufs; tmp++)
235     {
236         thisWd = CPS_UncachedRead32(&(thisDesc->word[0]));
237         if (thisWd & CEDI_RXD_USED)
238             count++;
239         else
240             break;
241         if (thisWd & CEDI_RXD_WRAP)
242             thisDesc = rxQ->rxDescStart;
243         else
244             thisDesc = (rxDesc *)(((uintptr_t)(thisDesc))
245                                     + (CEDI_PdVar(rxDescriptorSize)));
246     }
247     return count;
248 }
249 
250 /**
251  * Read first unread descriptor (at tail of queue): if new data is available
252  * it swaps out the buffer and replaces it with a new one, clears the
253  * descriptor for re-use, then updates the driver queue-pointer.
254  * Checks for Start Of Frame (SOF) and End Of Frame (EOF) flags in the
255  * descriptors, passing back in return value.
256  * If EOF set, the descriptor status is returned via rxDescStat.
257  * @param[in] pD driver private state info specific to this instance
258  * @param[in] queueNum
259  *   number of the Rx queue
260  * @param[in,out] buf pointer to address of memory for new buffer to add to Rx
261  *   descriptor queue, if data is available the buffer addresses for this are
262  *   returned in buf, else if no data available the new buffer can be re-used.
263  *   Physical address of buffer is checked for word-alignment in 64/128-bit
264  *   width cases.
265  * @param[in] init if >0 then initialise the (new) buffer data to all zeros.
266  *    Ignored if no data available.
267  * @param[out] descData pointer for returning status & descriptor data
268  *   Struct fields:
269  *
270  *    uint32_t rxDescStat  - Rx descriptor status word
271  *
272  *    uint8_t status    - Rx data status, one of the following values:
273  *      CEDI_RXDATA_SOF_EOF  :data available, single-buffer frame (SOF & EOF
274  *                            set)
275  *      CEDI_RXDATA_SOF_ONLY :data available, start of multi-buffer frame
276  *      CEDI_RXDATA_NO_FLAG  :data available, intermediate buffer of multi-
277  *                            buffer frame
278  *      CEDI_RXDATA_EOF_ONLY :data available, end of multi-buffer frame
279  *      CEDI_RXDATA_NODATA   :no data available
280  *
281  *    CEDI_TimeStampData rxTsData - Rx descriptor timestamp when valid
282  *                                  (rxTsData->tsValid will be set to 1)
283  *
284  * @return 0 if successful,
285  * @return EINVAL if invalid queueNum, buf, rxDescStat or
286  *    status parameters
287  */
emacReadRxBuf(void * pD,uint8_t queueNum,CEDI_BuffAddr * buf,uint8_t init,CEDI_RxDescData * descData)288 uint32_t emacReadRxBuf(void *pD, uint8_t queueNum, CEDI_BuffAddr *buf,
289                         uint8_t init, CEDI_RxDescData *descData)
290 {
291     uint32_t tmp, bufLenWords, descWd0;
292     CEDI_BuffAddr oldbuf;
293     uint8_t wdNum, tailWrap;
294     uint32_t tsLowerWd, tsUpperWd;
295     rxQueue_t *rxQ;
296 
297     if (!pD) return EINVAL;
298 
299 //    vDbgMsg(DBG_GEN_MSG, 10, "%s entered (regBase %08lX)\n", __func__,
300 //                CEDI_PdVar(cfg).regBase);
301 
302     if (buf==NULL) {
303         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: NULL buf parameter");
304         return EINVAL;
305     }
306 
307     if (descData==NULL) {
308         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: NULL descData parameter");
309         return EINVAL;
310     }
311 
312     if (queueNum>=(CEDI_PdVar(cfg)).rxQs) {
313         vDbgMsg(DBG_GEN_MSG, 5, "Error: Invalid Rx queue number - %u\n", queueNum);
314         return EINVAL;
315     }
316 
317     if ((buf->vAddr==0) || (buf->pAddr==0)) {
318         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: NULL buf address");
319         return EINVAL;
320     }
321 
322     /* alignment checking for new buffer */
323     switch (CEDI_PdVar(cfg).dmaBusWidth) {
324     case CEDI_DMA_BUS_WIDTH_32:
325         tmp = 4; break;
326     case CEDI_DMA_BUS_WIDTH_64:
327         tmp = 8; break;
328     case CEDI_DMA_BUS_WIDTH_128:
329         tmp = 16; break;
330     default: tmp = 4; break;
331     }
332     if ((buf->pAddr)%tmp) {
333         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: Rx buffer not word-aligned");
334         return EINVAL;
335     }
336 
337     rxQ = &(CEDI_PdVar(rxQueue[queueNum]));
338 
339     /* get first descriptor & test used bit */
340     descWd0 = CPS_UncachedRead32(&(rxQ->rxDescTail->word[0]));
341 
342     if (descWd0 & CEDI_RXD_USED) {
343         /* new data received - read & process descriptor */
344 
345         /* get old physical address */
346         oldbuf.pAddr = descWd0 & CEDI_RXD_ADDR_MASK;
347 
348 #ifdef CEDI_64B_COMPILE
349         /* upper 32 bits if 64 bit addressing */
350         if (CEDI_PdVar(cfg).dmaAddrBusWidth)
351             oldbuf.pAddr |= ((uint64_t)CPS_UncachedRead32(
352                                         &(rxQ->rxDescTail->word[2])))<<32;
353 #endif
354 
355         /* get old virtual address & clear from list */
356         oldbuf.vAddr = *(rxQ->rxTailVA);
357         *(rxQ->rxTailVA) = 0;
358 
359         /* save new virtual address */
360         *(rxQ->rxStopVA) = buf->vAddr;
361 
362         bufLenWords = (CEDI_PdVar(cfg).rxBufLength[queueNum])<<4;
363         if (init)
364             for (tmp=0; tmp<bufLenWords; tmp++)
365                 CPS_UncachedWrite32((uint32_t *)(buf->vAddr+4*tmp), 0);
366 
367         /* read Rx status */
368         descData->rxDescStat = CPS_UncachedRead32(&(rxQ->rxDescTail->word[1]));
369 
370         /* extract timestamp if available */
371         if ((CEDI_PdVar(cfg).enRxExtBD) && (descWd0 & CEDI_RXD_TS_VALID)) {
372         uint32_t reg;
373             descData->rxTsData.tsValid = 1;
374                         // position depends on 32/64 bit addr
375             wdNum = (CEDI_PdVar(cfg).dmaAddrBusWidth)?4:2;
376 
377             tsLowerWd = CPS_UncachedRead32(&(rxQ->rxDescTail->word[wdNum]));
378             tsUpperWd = CPS_UncachedRead32(&(rxQ->rxDescTail->word[wdNum+1]));
379 
380             descData->rxTsData.tsNanoSec = tsLowerWd & CEDI_TS_NANO_SEC_MASK;
381             descData->rxTsData.tsSecs =
382                     (((tsUpperWd & CEDI_TS_SEC1_MASK)<<CEDI_TS_SEC1_POS_SHIFT)
383                         | (tsLowerWd >> CEDI_TS_SEC0_SHIFT));
384 
385         /* The timestamp only contains lower few bits of seconds, so add value from 1588 timer */
386         reg =  CPS_UncachedRead32(CEDI_RegAddr(tsu_timer_sec));
387         /* If the top bit is set in the timestamp, but not in 1588 timer, it has rolled over, so subtract max size */
388         if ((descData->rxTsData.tsSecs & (CEDI_TS_SEC_TOP>>1)) && !(reg & (CEDI_TS_SEC_TOP>>1))) {
389         descData->rxTsData.tsSecs -= (CEDI_TS_SEC_TOP<<1);
390 
391         }
392         descData->rxTsData.tsSecs += ((~CEDI_TS_SEC_MASK) & EMAC_REGS__TSU_TIMER_SEC__TIMER__READ(reg));
393     }
394     else
395     {
396         descData->rxTsData.tsValid = 0;
397     }
398 
399         /* save this for later */
400         tailWrap = descWd0 & CEDI_RXD_WRAP;
401 
402                 /* write back to descriptors */
403         CPS_UncachedWrite32(&(rxQ->rxDescTail->word[1]), CEDI_RXD_EMPTY);
404         /* zero buf physical address & set used - this will be new end-stop */
405         CPS_UncachedWrite32(&(rxQ->rxDescTail->word[0]),
406                                 CEDI_RXD_USED | (tailWrap?CEDI_RXD_WRAP:0));
407 
408         /* handle old "stop" descriptor now */
409         /* insert new buf physical address & clear used */
410         descWd0 = CPS_UncachedRead32(&(rxQ->rxDescStop->word[0]));
411         descWd0 = ((buf->pAddr) & CEDI_RXD_ADDR_MASK) |
412                     (descWd0 & CEDI_RXD_WRAP);
413         CPS_UncachedWrite32(&(rxQ->rxDescStop->word[0]), descWd0);
414         /* upper 32 bits if 64 bit addressing */
415         if (CEDI_PdVar(cfg).dmaAddrBusWidth) {
416 #ifdef CEDI_64B_COMPILE
417             /* 64-bit addressing */
418             CPS_UncachedWrite32(&(rxQ->rxDescStop->word[2]),
419                              (buf->pAddr & 0xFFFFFFFF00000000)>>32);
420 #else
421             /* 32-bit addressing */
422             CPS_UncachedWrite32(&(rxQ->rxDescStop->word[2]), 0x00000000);
423 #endif
424         }
425 
426         /* update pointers */
427         rxQ->rxDescStop = rxQ->rxDescTail;
428         rxQ->rxStopVA = rxQ->rxTailVA;
429         if (tailWrap) {
430             rxQ->rxDescTail = rxQ->rxDescStart;
431             rxQ->rxTailVA = rxQ->rxBufVAddr;
432         }
433         else {
434             rxQ->rxDescTail = (rxDesc *)(((uintptr_t)(rxQ->rxDescTail))
435                                         + (CEDI_PdVar(rxDescriptorSize)));
436             rxQ->rxTailVA++;
437         }
438 
439         /* return old buffer addresses */
440         buf->pAddr = oldbuf.pAddr;
441         buf->vAddr = oldbuf.vAddr;
442 /*        vDbgMsg(DBG_GEN_MSG, 10, "%s vAddr=%p pAddr=%p\n",
443                       __func__, (void *)buf->vAddr, (void *)buf->pAddr);*/
444 
445 
446         /* work out read frame status */
447         if ((descData->rxDescStat) & CEDI_RXD_SOF) {
448             if ((descData->rxDescStat) & CEDI_RXD_EOF)
449                 descData->status = CEDI_RXDATA_SOF_EOF;
450             else
451                 descData->status = CEDI_RXDATA_SOF_ONLY;
452         }
453         else
454         {
455             if ((descData->rxDescStat) & CEDI_RXD_EOF)
456                 descData->status = CEDI_RXDATA_EOF_ONLY;
457             else
458                 descData->status = CEDI_RXDATA_NO_FLAG;
459         }
460     }
461     else
462         descData->status = CEDI_RXDATA_NODATA;
463 
464     return 0;
465 }
466 
467 /* Decode the Rx descriptor status into a bit-field struct
468  * @param pD - driver private state info specific to this instance
469  * @param rxDStatWord - Rx descriptor status word
470  * @param rxDStat - pointer to bit-field struct for decoded status fields
471  */
emacGetRxDescStat(void * pD,uint32_t rxDStatWord,CEDI_RxDescStat * rxDStat)472 void emacGetRxDescStat(void *pD, uint32_t rxDStatWord, CEDI_RxDescStat *rxDStat)
473 {
474     uint32_t reg, wd1;
475 
476     if ((NULL==pD) || (NULL==rxDStat)) return;
477 
478     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
479 
480     wd1 = rxDStatWord;
481     rxDStat->bufLen = wd1 & CEDI_RXD_LEN_MASK;
482     if (EMAC_REGS__NETWORK_CONFIG__JUMBO_FRAMES__READ(reg) ||
483         (EMAC_REGS__NETWORK_CONFIG__IGNORE_RX_FCS__READ(reg)==0)) {
484         rxDStat->bufLen |= wd1 & CEDI_RXD_LEN13_FCS_STAT;
485         rxDStat->fcsStatus = 0;
486     }
487     else
488         rxDStat->fcsStatus = (wd1 & CEDI_RXD_LEN13_FCS_STAT)?1:0;
489 
490     rxDStat->sof = (wd1 & CEDI_RXD_SOF)?1:0;
491     rxDStat->eof = (wd1 & CEDI_RXD_EOF)?1:0;
492     rxDStat->header = (!rxDStat->eof && (wd1 & CEDI_RXD_HDR))?1:0;
493     rxDStat->eoh = (!rxDStat->eof && (wd1 & CEDI_RXD_EOH))?1:0;
494     rxDStat->vlanTagDet = (wd1 & CEDI_RXD_VLAN_TAG)?1:0;
495     rxDStat->cfi = ((wd1 & CEDI_RXD_CFI) && rxDStat->vlanTagDet)?1:0;
496     if (rxDStat->vlanTagDet)
497         rxDStat->vlanPri =
498                 (wd1 & CEDI_RXD_VLAN_PRI_MASK)>>CEDI_RXD_VLAN_PRI_SHIFT;
499     else
500         rxDStat->vlanPri = 0;
501     rxDStat->priTagDet = (wd1 & CEDI_RXD_PRI_TAG)?1:0;
502     if (EMAC_REGS__NETWORK_CONFIG__RECEIVE_CHECKSUM_OFFLOAD_ENABLE__READ(reg)) {
503         rxDStat->chkOffStat = (wd1 & CEDI_RXD_TYP_IDR_CHK_STA_MASK)\
504                                     >>CEDI_RXD_TYP_IDR_CHK_STA_SHIFT;
505         rxDStat->snapNoVlanCfi = (wd1 & CEDI_RXD_TYP_MAT_SNP_NCFI)?1:0;
506         rxDStat->typeMatchReg = 0;
507         rxDStat->typeIdMatch = 0;
508     }
509     else {
510         rxDStat->chkOffStat = 0;
511         rxDStat->snapNoVlanCfi = 0;
512         rxDStat->typeMatchReg = (wd1 & CEDI_RXD_TYP_IDR_CHK_STA_MASK)\
513                                     >>CEDI_RXD_TYP_IDR_CHK_STA_SHIFT;
514         rxDStat->typeIdMatch = (wd1 & CEDI_RXD_TYP_MAT_SNP_NCFI)?1:0;
515     }
516 
517     rxDStat->specAddReg = (wd1 & CEDI_RXD_SPEC_REG_MASK)\
518                                 >>CEDI_RXD_SPEC_REG_SHIFT;
519     if (CEDI_PdVar(hwCfg).rx_pkt_buffer &&
520             (CEDI_PdVar(hwCfg).num_spec_add_filters>4))
521     {   /* extra spec. addr matching variation */
522         rxDStat->specAddReg += ((wd1 & CEDI_RXD_SPEC_ADD_MAT)?1:0) << 2;
523         rxDStat->specAddMatch = (wd1 & CEDI_RXD_EXT_ADD_MAT)?1:0;
524         rxDStat->extAddrMatch = 0;
525     }
526     else
527     {
528         rxDStat->specAddMatch = (wd1 & CEDI_RXD_SPEC_ADD_MAT)?1:0;
529         rxDStat->extAddrMatch = (wd1 & CEDI_RXD_EXT_ADD_MAT)?1:0;
530     }
531     rxDStat->uniHashMatch = (wd1 & CEDI_RXD_UNI_HASH_MAT)?1:0;
532     rxDStat->multiHashMatch = (wd1 & CEDI_RXD_MULTI_HASH_MAT)?1:0;
533     rxDStat->broadcast = (wd1 & (uint32_t)CEDI_RXD_BROADCAST_DET)?1:0;
534 }
535 
536 /* Provide the size of descriptor calculated for the current configuration.
537  * @param pD - driver private state info specific to this instance
538  * @param rxDescSize - pointer to Rx descriptor Size
539  */
emacGetRxDescSize(void * pD,uint32_t * rxDescSize)540 void emacGetRxDescSize(void *pD, uint32_t *rxDescSize)
541 {
542     if ((pD==NULL)||(rxDescSize==NULL))
543         return;
544     *rxDescSize = CEDI_PdVar(rxDescriptorSize);
545 }
546 
547 /* Get state of receiver
548  * @param pD - driver private state info specific to this instance
549  * @return 1 if enabled
550  * @return 0 if disabled or pD==NULL
551  */
emacRxEnabled(void * pD)552 uint32_t emacRxEnabled(void *pD)
553 {
554     uint32_t reg;
555     if (pD==NULL) return 0;
556     reg = CPS_UncachedRead32(CEDI_RegAddr(network_control));
557     return EMAC_REGS__NETWORK_CONTROL__ENABLE_RECEIVE__READ(reg);
558 }
559 
560 /* Enable the receive circuit.
561  * @param pD - driver private state info specific to this instance
562  */
emacEnableRx(void * pD)563 void emacEnableRx(void *pD)
564 {
565     uint32_t reg;
566     if (!pD) return;
567     reg = CPS_UncachedRead32(CEDI_RegAddr(network_control));
568     EMAC_REGS__NETWORK_CONTROL__ENABLE_RECEIVE__SET(reg);
569     CPS_UncachedWrite32(CEDI_RegAddr(network_control), reg);
570 }
571 
572 /* Disable the receive circuit.
573  * @param pD - driver private state info specific to this instance
574  */
emacDisableRx(void * pD)575 void emacDisableRx(void *pD)
576 {
577     uint32_t reg;
578     if (!pD) return;
579     reg = CPS_UncachedRead32(CEDI_RegAddr(network_control));
580     EMAC_REGS__NETWORK_CONTROL__ENABLE_RECEIVE__CLR(reg);
581     CPS_UncachedWrite32(CEDI_RegAddr(network_control), reg);
582 }
583 
584 /* Remove a buffer from the end of the receive buffer queue.  This function is
585  * intended to be used when shutting down the driver, prior to deallocating the
586  * receive buffers, and should not be called while Rx is enabled or unread
587  * data remains in the queue.
588  * @param pD - driver private state info specific to this instance
589  * @param queueNum - number of the Rx queue (range 0 to rxQs-1)
590  * @param buf - pointer to struct for returning virtual and physical addresses
591  *  of buffer.
592  * @return 0 if successful
593  * @return EINVAL if invalid queueNum, ENOENT if no buffers left to free
594  */
emacRemoveRxBuf(void * pD,uint8_t queueNum,CEDI_BuffAddr * buf)595 uint32_t emacRemoveRxBuf(void *pD, uint8_t queueNum, CEDI_BuffAddr *buf)
596 {
597     uint32_t tmp;
598     rxQueue_t *rxQ;
599 
600     if (!pD) return EINVAL;
601 
602     if (queueNum>=(CEDI_PdVar(cfg)).rxQs) {
603         vDbgMsg(DBG_GEN_MSG, 5, "Error: Invalid Rx queue number: %u\n", queueNum);
604         return EINVAL;
605     }
606 
607     if (buf==0) {
608         vDbgMsg(DBG_GEN_MSG, 5, "%s\n", "Error: NULL buf parameter");
609         return EINVAL;
610     }
611 
612     rxQ = &(CEDI_PdVar(rxQueue[queueNum]));
613 
614     if (0==rxQ->numRxBufs)
615         return ENOENT;
616 
617     /* skip "stop" descriptor since no buffer there */
618     if ((rxQ->rxDescEnd==rxQ->rxDescStop) && (rxQ->rxDescEnd!=rxQ->rxDescStart))
619     {
620         rxQ->rxDescEnd = (rxDesc*)
621                 ((uintptr_t)(rxQ->rxDescEnd) - CEDI_PdVar(rxDescriptorSize));
622     rxQ->rxEndVA--;
623     }
624 
625     /* get physical address */
626     buf->pAddr = CPS_UncachedRead32(&(rxQ->rxDescEnd->word[0]))
627                                             & CEDI_RXD_ADDR_MASK;
628     /* get virtual address */
629     buf->vAddr = *(rxQ->rxEndVA);
630 
631     /* dec end/tail pointers unless already at start of list */
632     if (rxQ->rxDescEnd!=rxQ->rxDescStart) {
633         rxQ->rxDescEnd = (rxDesc*)
634                 ((uintptr_t)(rxQ->rxDescEnd) - CEDI_PdVar(rxDescriptorSize));
635         rxQ->rxEndVA--;
636 
637         /* set wrap on new end descriptor */
638         tmp = CPS_UncachedRead32(&(rxQ->rxDescEnd->word[0]));
639         CPS_UncachedWrite32(&(rxQ->rxDescEnd->word[0]), tmp | CEDI_RXD_WRAP);
640     }
641     rxQ->numRxBufs--;
642 
643     return 0;
644 }
645 
emacFindQBaseAddr(void * pD,uint8_t queueNum,rxQueue_t * rxQ,uint32_t * pAddr,uintptr_t * vAddr)646 void emacFindQBaseAddr(void *pD, uint8_t queueNum, rxQueue_t *rxQ,
647                         uint32_t *pAddr, uintptr_t *vAddr) {
648     uint8_t q = 0;
649     /* find start addresses for this rxQ */
650     *vAddr = CEDI_PdVar(cfg).rxQAddr;
651     *pAddr = CEDI_PdVar(cfg).rxQPhyAddr;
652 
653     if (queueNum>0)
654         rxQ->rxBufVAddr = (CEDI_PdVar(rxQueue[0]).rxBufVAddr);
655     while (q<queueNum) {
656         *vAddr += (rxQ->numRxDesc)*(CEDI_PdVar(rxDescriptorSize));//sizeof(rxDesc);
657         *pAddr += (rxQ->numRxDesc)*(CEDI_PdVar(rxDescriptorSize));//sizeof(rxDesc);
658         rxQ->rxBufVAddr += rxQ->numRxDesc;
659         q++;
660     }
661     vDbgMsg(DBG_GEN_MSG, 10, "%s: base address Q%u virt=%08lX phys=%08X vAddrList=%p\n",
662             __func__, queueNum, *vAddr, *pAddr, rxQ->rxBufVAddr);
663 }
664 /* Reset Rx buffer descriptor list/ buffer virtual address list to initial
665  * empty state, clearing all descriptors.  For use by init or after a fatal
666  * error. Disables receive circuit.
667  * @param pD - driver private state info specific to this instance
668  * @param queueNum - number of the Rx queue (range 0 to rxQs-1)
669  * @param ptrsOnly - if =1, then reset pointers and clearing used bits only
670  *          after a link down/up event (assume buffers already assigned)
671  *          if =0, initialise all list fields for this queue, including
672  *          clearing buffer addresses
673  * @return 0 if successful
674  * @return EINVAL if invalid parameter
675  */
emacResetRxQ(void * pD,uint8_t queueNum,uint8_t ptrsOnly)676 uint32_t emacResetRxQ(void *pD, uint8_t queueNum, uint8_t ptrsOnly)
677 {
678 #define CEDI_WR_RXQ_PTR_REG_N_CASE(Q) case Q:\
679         CPS_UncachedWrite32(CEDI_RegAddr(receive_q##Q##_ptr), regTmp);\
680         break;
681 
682     uint32_t regTmp;
683     uint16_t i;
684     uint32_t pAddr;
685     uintptr_t vAddr;
686     rxDesc* descPtr;
687     rxQueue_t *rxQ;
688 
689     if ((pD==NULL) || (queueNum>=CEDI_PdVar(cfg).rxQs) || (ptrsOnly>1))
690         return EINVAL;
691 
692     emacDisableRx(pD);
693 
694     rxQ = &(CEDI_PdVar(rxQueue[queueNum]));
695     emacFindQBaseAddr(pD, queueNum, rxQ, &pAddr, &vAddr);
696 
697     /* want the virtual addresses here: */
698     if (ptrsOnly) {
699         if (rxQ->rxDescStop!=rxQ->rxDescEnd) {
700         /* copy buffer addresses from new "stop" descriptor to old one,
701          * before reset pointers */
702             CPS_UncachedWrite32((uint32_t *)&(rxQ->rxDescStop->word[0]),
703                 CPS_UncachedRead32((uint32_t *)&(rxQ->rxDescEnd->word[0])));
704             *(rxQ->rxStopVA) = *(rxQ->rxEndVA);
705         }
706     }
707     else
708     {
709     rxQ->rxDescStart = (rxDesc *)vAddr;
710         rxQ->rxDescEnd = (rxDesc *)vAddr;
711     }
712     rxQ->rxDescStop = (rxDesc *)vAddr;
713     rxQ->rxDescTail = (rxDesc *)vAddr;
714     rxQ->rxTailVA = rxQ->rxBufVAddr;
715     rxQ->rxStopVA = rxQ->rxBufVAddr;
716     if (!ptrsOnly) {
717         rxQ->rxEndVA = rxQ->rxBufVAddr;
718         *(rxQ->rxStopVA) = 0;
719         rxQ->numRxBufs = 0;
720     }
721 
722     /* full reset: clear used flags except stop & set wrap flag, only expand
723      * available size as buffers are added - if ptrsOnly, then buffers already
724      * in ring, preserve addresses & only clear used bits/wd1  */
725     descPtr = rxQ->rxDescStart;
726     for (i = 0; i<rxQ->numRxDesc; i++) {
727         if (ptrsOnly) {
728             if (rxQ->rxDescStop==rxQ->rxDescEnd) {
729                 CPS_UncachedWrite32((uint32_t *)&(rxQ->rxDescStop->word[0]),
730                                           CEDI_RXD_WRAP|CEDI_RXD_USED );
731                 CPS_UncachedWrite32(&(rxQ->rxDescStop->word[1]), CEDI_RXD_EMPTY);
732                 *(rxQ->rxStopVA) = 0;
733             }
734             else
735             {
736                 pAddr = CPS_UncachedRead32((uint32_t *)&(rxQ->rxDescStop->word[0]));
737                 CPS_UncachedWrite32((uint32_t *)&(rxQ->rxDescStop->word[0]),
738                                     pAddr & ~(CEDI_RXD_WRAP|CEDI_RXD_USED));
739                 CPS_UncachedWrite32(&(rxQ->rxDescStop->word[1]), CEDI_RXD_EMPTY);
740                 /* inc stop pointer */
741                 rxQ->rxDescStop = (rxDesc *)(((uintptr_t)rxQ->rxDescStop) +
742                                     (CEDI_PdVar(rxDescriptorSize)));
743                 /* inc VA stop pointer */
744                 rxQ->rxStopVA++;
745             }
746         }
747         else {
748         CPS_UncachedWrite32((uint32_t *)
749                 &(descPtr->word[0]), i?0:CEDI_RXD_WRAP|CEDI_RXD_USED);
750         CPS_UncachedWrite32((uint32_t *)
751                 &(descPtr->word[1]), CEDI_RXD_EMPTY);
752             descPtr = (rxDesc*) (((uintptr_t)(descPtr)) +
753                 (CEDI_PdVar(rxDescriptorSize)));
754         }
755     }
756 
757     if (!ptrsOnly) {
758         /* write hardware base address register */
759         regTmp = 0;
760         EMAC_REGS__RECEIVE_Q_PTR__DMA_RX_Q_PTR__MODIFY(regTmp, pAddr>>2);
761         switch (queueNum) {
762         case 0:
763             CPS_UncachedWrite32(CEDI_RegAddr(receive_q_ptr), regTmp);
764             break;
765         CEDI_WR_RXQ_PTR_REG_N_CASE(1);
766         CEDI_WR_RXQ_PTR_REG_N_CASE(2);
767         CEDI_WR_RXQ_PTR_REG_N_CASE(3);
768         CEDI_WR_RXQ_PTR_REG_N_CASE(4);
769         CEDI_WR_RXQ_PTR_REG_N_CASE(5);
770         CEDI_WR_RXQ_PTR_REG_N_CASE(6);
771         CEDI_WR_RXQ_PTR_REG_N_CASE(7);
772         CEDI_WR_RXQ_PTR_REG_N_CASE(8);
773         CEDI_WR_RXQ_PTR_REG_N_CASE(9);
774         CEDI_WR_RXQ_PTR_REG_N_CASE(10);
775         CEDI_WR_RXQ_PTR_REG_N_CASE(11);
776         CEDI_WR_RXQ_PTR_REG_N_CASE(12);
777         CEDI_WR_RXQ_PTR_REG_N_CASE(13);
778         CEDI_WR_RXQ_PTR_REG_N_CASE(14);
779         CEDI_WR_RXQ_PTR_REG_N_CASE(15);
780         }
781     }
782     return 0;
783 }
784 
785 /* Return the content of EMAC receive status register
786  * @param pD - driver private state info specific to this instance
787  * @param status - pointer to struct with fields for each flag
788  * @return =1 if any flags set, =0 if not or status=NULL.
789  */
emacGetRxStatus(void * pD,CEDI_RxStatus * status)790 uint32_t emacGetRxStatus(void *pD, CEDI_RxStatus *status)
791 {
792     uint32_t reg;
793     if ((pD==NULL)||(status==NULL))
794         return 0;
795 
796     reg = CPS_UncachedRead32(CEDI_RegAddr(receive_status));
797 
798     status->buffNotAvail =
799             EMAC_REGS__RECEIVE_STATUS__BUFFER_NOT_AVAILABLE__READ(reg);
800     status->frameRx =
801             EMAC_REGS__RECEIVE_STATUS__FRAME_RECEIVED__READ(reg);
802     status->rxOverrun =
803             EMAC_REGS__RECEIVE_STATUS__RECEIVE_OVERRUN__READ(reg);
804     status->hRespNotOk =
805             EMAC_REGS__RECEIVE_STATUS__RESP_NOT_OK__READ(reg);
806 
807     return reg?1:0;
808 }
809 
810 /* Reset the bits of EMAC receive status register as selected in resetStatus
811  * @param pD - driver private state info specific to this instance
812  * @param resetStatus - OR'd combination of CEDI_RXS_ bit-fields
813  */
emacClearRxStatus(void * pD,uint32_t resetStatus)814 void emacClearRxStatus(void *pD, uint32_t resetStatus)
815 {
816     uint32_t reg = 0;
817     if (!pD) return;
818 
819     if (resetStatus & CEDI_RXS_NO_BUFF)
820         reg |= CEDI_RXS_NO_BUFF;
821 
822     if (resetStatus & CEDI_RXS_FRAME_RX)
823         reg |= CEDI_RXS_FRAME_RX;
824 
825     if (resetStatus & CEDI_RXS_OVERRUN)
826         reg |= CEDI_RXS_OVERRUN;
827 
828     if (resetStatus & CEDI_RXS_HRESP_ERR)
829         reg |= CEDI_RXS_HRESP_ERR;
830 
831     CPS_UncachedWrite32(CEDI_RegAddr(receive_status), reg);
832 }
833 
834 /**
835  *  Enable/disable header-data split feature.
836  *  When enabled, frame L2/L3/L4 headers will written to separate
837  *  buffer, before data starts in a second buffer (if not zero payload)
838  */
emacSetHdrDataSplit(void * pD,uint8_t enable)839 uint32_t emacSetHdrDataSplit(void *pD, uint8_t enable) {
840 
841     uint32_t reg;
842     if ((pD==NULL) || (enable>1))
843         return EINVAL;
844     if (CEDI_PdVar(hwCfg).hdr_split==0)
845         return ENOTSUP;
846 
847     reg = CPS_UncachedRead32(CEDI_RegAddr(dma_config));
848     if (enable)
849         EMAC_REGS__DMA_CONFIG__HDR_DATA_SPLITTING_EN__SET(reg);
850     else
851         EMAC_REGS__DMA_CONFIG__HDR_DATA_SPLITTING_EN__CLR(reg);
852 
853     CPS_UncachedWrite32(CEDI_RegAddr(dma_config), reg);
854     return EOK;
855 }
856 
857 /**
858  * Read enable/disable status for header-data split feature
859  */
emacGetHdrDataSplit(void * pD,uint8_t * enable)860 uint32_t emacGetHdrDataSplit(void *pD, uint8_t *enable) {
861 
862     if ((pD==NULL) || (enable==NULL))
863         return EINVAL;
864     if (CEDI_PdVar(hwCfg).hdr_split==0)
865         return ENOTSUP;
866 
867     *enable = EMAC_REGS__DMA_CONFIG__HDR_DATA_SPLITTING_EN__READ(
868                 CPS_UncachedRead32(CEDI_RegAddr(dma_config)));
869 
870     return EOK;
871 }
872 
873 /**
874  *  Enable/disable Receive Segment Coalescing function.
875  *  When enabled, consecutive TCP/IP frames on a priority queue
876  *  will be combined to form a single large frame
877  */
emacSetRscEnable(void * pD,uint8_t queue,uint8_t enable)878 uint32_t emacSetRscEnable(void *pD, uint8_t queue, uint8_t enable) {
879 
880     uint32_t reg, enableField;
881     if (pD==NULL)
882         return EINVAL;
883     if (CEDI_PdVar(hwCfg).pbuf_rsc==0)
884         return ENOTSUP;
885     if ((queue<1) || (queue>=(CEDI_PdVar(cfg)).rxQs) || (enable>1))
886         return EINVAL;
887 
888     reg = CPS_UncachedRead32(CEDI_RegAddr(rsc_control));
889     enableField = EMAC_REGS__RSC_CONTROL__RSC_CONTROL__READ(reg);
890 
891     if (enable)
892         enableField |= (1 << (queue-1));
893     else
894         enableField &= ~(1 << (queue-1));
895 
896     EMAC_REGS__RSC_CONTROL__RSC_CONTROL__MODIFY(reg, enableField);
897     CPS_UncachedWrite32(CEDI_RegAddr(rsc_control), reg);
898 
899     return EOK;
900 }
901 
902 /**
903  * Read enabled status of RSC on a specified priority queue
904  */
emacGetRscEnable(void * pD,uint8_t queue,uint8_t * enable)905 uint32_t emacGetRscEnable(void *pD, uint8_t queue, uint8_t *enable) {
906 
907     uint32_t reg;
908     if ((pD==NULL) || (enable==NULL))
909         return EINVAL;
910     if ((queue<1)||(queue>=(CEDI_PdVar(cfg)).rxQs))
911         return EINVAL;
912     if (CEDI_PdVar(hwCfg).pbuf_rsc==0)
913         return ENOTSUP;
914 
915     reg = CPS_UncachedRead32(CEDI_RegAddr(rsc_control));
916     *enable = (EMAC_REGS__RSC_CONTROL__RSC_CONTROL__READ(reg)
917                             & (1<<(queue-1)))?1:0;
918 
919     return EOK;
920 }
921 
922 /**
923  *  Set/Clear Mask of Receive Segment Coalescing disabling.
924  *  When mask is set and RSC is enabled, the RSC operation is not
925  *  disabled by receipt of frame with an end-coalesce flag set
926  *  (SYN/FIN/RST/URG)
927  */
emacSetRscClearMask(void * pD,uint8_t setMask)928 uint32_t emacSetRscClearMask(void *pD, uint8_t setMask) {
929 
930     uint32_t reg;
931     if ((pD==NULL) || (setMask>1))
932         return EINVAL;
933     if (CEDI_PdVar(hwCfg).pbuf_rsc==0)
934         return ENOTSUP;
935 
936     reg = CPS_UncachedRead32(CEDI_RegAddr(rsc_control));
937     if (setMask)
938         reg |= (1<<16);
939     else
940         reg &= ~(1<<16);
941     CPS_UncachedWrite32(CEDI_RegAddr(rsc_control), reg);
942 
943     return EOK;
944 }
945 
emacSetRxPartialStFwd(void * pD,uint32_t watermark,uint8_t enable)946 uint32_t emacSetRxPartialStFwd(void *pD, uint32_t watermark, uint8_t enable)
947 {
948     uint32_t reg;
949     if (!pD) return EINVAL;
950     if (CEDI_PdVar(hwCfg).rx_pkt_buffer==0)
951         return ENOTSUP;
952     if (enable>1) return EINVAL;
953 //    if ((enable) && (!CEDI_PdVar(hwCfg).rx_pkt_buffer))
954 //        return EINVAL;
955     if (watermark>((1UL<<CEDI_PdVar(hwCfg).rx_pbuf_addr)-1))
956         return EINVAL;
957 
958     reg = CPS_UncachedRead32(CEDI_RegAddr(pbuf_rxcutthru));
959     if (enable) {
960         EMAC_REGS__PBUF_RXCUTTHRU__DMA_RX_CUTTHRU_THRESHOLD__MODIFY(reg,
961                 watermark);
962         EMAC_REGS__PBUF_RXCUTTHRU__DMA_RX_CUTTHRU__SET(reg);
963     }
964     else
965         EMAC_REGS__PBUF_RXCUTTHRU__DMA_RX_CUTTHRU__CLR(reg);
966 
967     CPS_UncachedWrite32(CEDI_RegAddr(pbuf_rxcutthru), reg);
968 
969     return 0;
970 }
971 
emacGetRxPartialStFwd(void * pD,uint32_t * watermark,uint8_t * enable)972 uint32_t emacGetRxPartialStFwd(void *pD, uint32_t *watermark, uint8_t *enable)
973 {
974     uint32_t reg;
975     if ((pD==0)||(enable==0)||(watermark==0))
976         return EINVAL;
977     if (CEDI_PdVar(hwCfg).rx_pkt_buffer==0)
978         return ENOTSUP;
979 
980     reg = CPS_UncachedRead32(CEDI_RegAddr(pbuf_rxcutthru));
981     (*enable) = EMAC_REGS__PBUF_RXCUTTHRU__DMA_RX_CUTTHRU__READ(reg);
982 
983     if (*enable)
984         *watermark = EMAC_REGS__PBUF_RXCUTTHRU__DMA_RX_CUTTHRU_THRESHOLD__READ(reg);
985 
986     return 0;
987 }
988 
989 /******************************** Rx Filtering ******************************/
990 
991   /**
992    * Set specific address register to the given address value
993    * @param[in] pD driver private state info specific to this instance
994    * @param[in] addrNum number of specific address filters,
995    *                in range 1 - num_spec_add_filters.
996    *    $RANGE $FROM 1 $TO CEDI_DesignCfg.num_spec_add_filters$
997    * @param[in] addr pointer to the 6-byte MAC address value to write
998    * @param[in] specFilterType flag specifying whether to use MAC source or
999    *    destination address to be compared for filtering. Source filter when =1.
1000    *    $RANGE $FROM 0 $TO 1 $
1001    * @param[in] byteMask  Bits masking out bytes of specific address from
1002    *    comparison.  When high, the associated address byte will be ignored.
1003    *    e.g. LSB of byteMask=1 implies first byte received should not be compared
1004    *    Ignored if addrNum=1, full bit masking available (SpecificAddr1Mask)
1005    *    $RANGE $FROM 0 $TO 0x3F $TEST_SUBSET 4 $
1006    * @return 0 if successful,
1007    * @return EINVAL if pD, addrNum, specFilterType or byteMask invalid
1008    * @return ENOTSUP if CEDI_DesignCfg.num_spec_add_filters==0
1009    */
emacSetSpecificAddr(void * pD,uint8_t addrNum,CEDI_MacAddress * addr,uint8_t specFilterType,uint8_t byteMask)1010 uint32_t emacSetSpecificAddr(void *pD, uint8_t addrNum, CEDI_MacAddress *addr,
1011                             uint8_t specFilterType, uint8_t byteMask)
1012 {
1013 #define CEDI_WR_SPEC_ADDR_CASE(reg) \
1014           case(reg):EMAC_REGS__SPEC_ADD_BOTTOM__ADDRESS__MODIFY(regVal,\
1015                       addr->byte[0] + (addr->byte[1]<<8) + \
1016                       (addr->byte[2]<<16) + (addr->byte[3]<<24));\
1017                     CPS_UncachedWrite32((CEDI_RegAddr(spec_add##reg##_bottom)),\
1018                                           regVal);\
1019                     regVal = 0;\
1020                     if (reg==1) {\
1021                       EMAC_REGS__SPEC_ADD_TOP_NO_MASK__ADDRESS__MODIFY(regVal,\
1022                         addr->byte[4] + (addr->byte[5]<<8));\
1023                       EMAC_REGS__SPEC_ADD_TOP_NO_MASK__FILTER_TYPE__MODIFY( \
1024                            regVal,specFilterType);\
1025                     } else {\
1026                       EMAC_REGS__SPEC_ADD_TOP__ADDRESS__MODIFY(regVal,\
1027                         addr->byte[4] + (addr->byte[5]<<8));\
1028                       EMAC_REGS__SPEC_ADD_TOP__FILTER_TYPE__MODIFY( \
1029                         regVal,specFilterType);\
1030                       EMAC_REGS__SPEC_ADD_TOP__FILTER_BYTE_MASK__MODIFY( \
1031                         regVal,byteMask);\
1032                     }\
1033                     CPS_UncachedWrite32((CEDI_RegAddr(spec_add##reg##_top)),\
1034                                           regVal); break;
1035 
1036     uint32_t regVal;
1037     if ((!pD)||(addr==NULL)) return EINVAL;
1038     if ((!addrNum) || (addrNum>(CEDI_PdVar(hwCfg).num_spec_add_filters)))
1039         return EINVAL;
1040     if ((specFilterType>1) || (byteMask>0x3F))
1041         return EINVAL;
1042 
1043     if (CEDI_PdVar(hwCfg).num_spec_add_filters==0)
1044         return ENOTSUP;
1045 
1046     regVal = 0;
1047     switch(addrNum) {
1048             CEDI_WR_SPEC_ADDR_CASE(1)
1049             CEDI_WR_SPEC_ADDR_CASE(2)
1050             CEDI_WR_SPEC_ADDR_CASE(3)
1051             CEDI_WR_SPEC_ADDR_CASE(4)
1052             CEDI_WR_SPEC_ADDR_CASE(5)
1053             CEDI_WR_SPEC_ADDR_CASE(6)
1054             CEDI_WR_SPEC_ADDR_CASE(7)
1055             CEDI_WR_SPEC_ADDR_CASE(8)
1056             CEDI_WR_SPEC_ADDR_CASE(9)
1057             CEDI_WR_SPEC_ADDR_CASE(10)
1058             CEDI_WR_SPEC_ADDR_CASE(11)
1059             CEDI_WR_SPEC_ADDR_CASE(12)
1060             CEDI_WR_SPEC_ADDR_CASE(13)
1061             CEDI_WR_SPEC_ADDR_CASE(14)
1062             CEDI_WR_SPEC_ADDR_CASE(15)
1063             CEDI_WR_SPEC_ADDR_CASE(16)
1064             CEDI_WR_SPEC_ADDR_CASE(17)
1065             CEDI_WR_SPEC_ADDR_CASE(18)
1066             CEDI_WR_SPEC_ADDR_CASE(19)
1067             CEDI_WR_SPEC_ADDR_CASE(20)
1068             CEDI_WR_SPEC_ADDR_CASE(21)
1069             CEDI_WR_SPEC_ADDR_CASE(22)
1070             CEDI_WR_SPEC_ADDR_CASE(23)
1071             CEDI_WR_SPEC_ADDR_CASE(24)
1072             CEDI_WR_SPEC_ADDR_CASE(25)
1073             CEDI_WR_SPEC_ADDR_CASE(26)
1074             CEDI_WR_SPEC_ADDR_CASE(27)
1075             CEDI_WR_SPEC_ADDR_CASE(28)
1076             CEDI_WR_SPEC_ADDR_CASE(29)
1077             CEDI_WR_SPEC_ADDR_CASE(30)
1078             CEDI_WR_SPEC_ADDR_CASE(31)
1079             CEDI_WR_SPEC_ADDR_CASE(32)
1080 }
1081 
1082     return EOK;
1083 }
1084 
1085   /**
1086    * Get the value of a specific address register
1087    * @param[in] pD driver private state info specific to this instance
1088    * @param[in] addrNum number of specific address filters, in
1089    *                range 1 - num_spec_add_filters
1090    * @param[out] specFilterType flag specifying whether to use MAC source or
1091    *    destination address for filtering. When set to 1 use source address.
1092    * @param[out] byteMask Bits masking out bytes of specific address from
1093    *    comparison.  When high, the associated address byte will be ignored.
1094    *    e.g. LSB of byteMask=1 implies first byte received should not be compared
1095    *    Ignored if addrNum=1, full bit masking available (SpecificAddr1Mask)
1096    * @param[out] addr pointer to a 6-byte MAC address struct for returning the
1097    *    address value
1098    * @return 0 if successful
1099    * @return EINVAL if pD, addrNum, specFilterType or byteMask invalid
1100    * @return ENOTSUP if CEDI_DesignCfg.num_spec_add_filters==0
1101    */
emacGetSpecificAddr(void * pD,uint8_t addrNum,CEDI_MacAddress * addr,uint8_t * specFilterType,uint8_t * byteMask)1102 uint32_t emacGetSpecificAddr(void *pD, uint8_t addrNum, CEDI_MacAddress *addr,
1103                         uint8_t *specFilterType, uint8_t *byteMask)
1104 {
1105 
1106 #define CEDI_RD_SPEC_ADDR_CASE(reg) \
1107               case(reg):\
1108               regAddrBottom = EMAC_REGS__SPEC_ADD_BOTTOM__ADDRESS__READ(\
1109                  CPS_UncachedRead32(CEDI_RegAddr(spec_add##reg##_bottom)));\
1110               regTopVal= CPS_UncachedRead32(CEDI_RegAddr(spec_add##reg##_top));\
1111               if (reg==1) {\
1112                 regAddrTop = EMAC_REGS__SPEC_ADD_TOP_NO_MASK__ADDRESS__READ(\
1113                             regTopVal);\
1114                 *specFilterType = \
1115                   EMAC_REGS__SPEC_ADD_TOP_NO_MASK__FILTER_TYPE__READ(regTopVal);\
1116                 *byteMask = 0;\
1117               } else {\
1118                 regAddrTop = EMAC_REGS__SPEC_ADD_TOP__ADDRESS__READ(regTopVal);\
1119                 *specFilterType = \
1120                   EMAC_REGS__SPEC_ADD_TOP__FILTER_TYPE__READ(regTopVal);\
1121                 *byteMask = \
1122                   EMAC_REGS__SPEC_ADD_TOP__FILTER_BYTE_MASK__READ(regTopVal);}\
1123               break;
1124 
1125     uint32_t regAddrTop, regAddrBottom, regTopVal;
1126     if ((pD==NULL)||(addr==NULL))
1127         return EINVAL;
1128 
1129     if ((specFilterType==NULL)||(byteMask==NULL))
1130         return EINVAL;
1131 
1132     if (CEDI_PdVar(hwCfg).num_spec_add_filters==0)
1133         return ENOTSUP;
1134     if ((!addrNum) || (addrNum>(CEDI_PdVar(hwCfg).num_spec_add_filters)))
1135         return EINVAL;
1136     regAddrTop = 0;
1137     regAddrBottom = 0;
1138     switch(addrNum) {
1139                 CEDI_RD_SPEC_ADDR_CASE(1)
1140                 CEDI_RD_SPEC_ADDR_CASE(2)
1141                 CEDI_RD_SPEC_ADDR_CASE(3)
1142                 CEDI_RD_SPEC_ADDR_CASE(4)
1143                 CEDI_RD_SPEC_ADDR_CASE(5)
1144                 CEDI_RD_SPEC_ADDR_CASE(6)
1145                 CEDI_RD_SPEC_ADDR_CASE(7)
1146                 CEDI_RD_SPEC_ADDR_CASE(8)
1147                 CEDI_RD_SPEC_ADDR_CASE(9)
1148                 CEDI_RD_SPEC_ADDR_CASE(10)
1149                 CEDI_RD_SPEC_ADDR_CASE(11)
1150                 CEDI_RD_SPEC_ADDR_CASE(12)
1151                 CEDI_RD_SPEC_ADDR_CASE(13)
1152                 CEDI_RD_SPEC_ADDR_CASE(14)
1153                 CEDI_RD_SPEC_ADDR_CASE(15)
1154                 CEDI_RD_SPEC_ADDR_CASE(16)
1155                 CEDI_RD_SPEC_ADDR_CASE(17)
1156                 CEDI_RD_SPEC_ADDR_CASE(18)
1157                 CEDI_RD_SPEC_ADDR_CASE(19)
1158                 CEDI_RD_SPEC_ADDR_CASE(20)
1159                 CEDI_RD_SPEC_ADDR_CASE(21)
1160                 CEDI_RD_SPEC_ADDR_CASE(22)
1161                 CEDI_RD_SPEC_ADDR_CASE(23)
1162                 CEDI_RD_SPEC_ADDR_CASE(24)
1163                 CEDI_RD_SPEC_ADDR_CASE(25)
1164                 CEDI_RD_SPEC_ADDR_CASE(26)
1165                 CEDI_RD_SPEC_ADDR_CASE(27)
1166                 CEDI_RD_SPEC_ADDR_CASE(28)
1167                 CEDI_RD_SPEC_ADDR_CASE(29)
1168                 CEDI_RD_SPEC_ADDR_CASE(30)
1169                 CEDI_RD_SPEC_ADDR_CASE(31)
1170                 CEDI_RD_SPEC_ADDR_CASE(32)
1171     }
1172 
1173 //    vDbgMsg(DBG_GEN_MSG, 10, "top=%08X  bottom=%08X\n",
1174 //                    regAddrTop, regAddrBottom);
1175     addr->byte[0] = (regAddrBottom & 0xFF);
1176     addr->byte[1] = ((regAddrBottom>>8) & 0xFF);
1177     addr->byte[2] = ((regAddrBottom>>16) & 0xFF);
1178     addr->byte[3] = ((regAddrBottom>>24) & 0xFF);
1179     addr->byte[4] = (regAddrTop & 0xFF);
1180     addr->byte[5] = ((regAddrTop>>8) & 0xFF);
1181     return EOK;
1182 }
1183 
1184 /* Set the specific address 1 mask register to the given value, allowing
1185  * address matching against a portion of the specific address 1 register
1186  * @param pD - driver private state info specific to this instance
1187  * @param mask - pointer to the address mask value to write
1188  * @return 0 if successful
1189  * @return EINVAL if mask=NULL
1190  * @return ENOTSUP if CEDI_DesignCfg.num_spec_add_filters==0
1191  */
emacSetSpecificAddr1Mask(void * pD,CEDI_MacAddress * mask)1192 uint32_t emacSetSpecificAddr1Mask(void *pD, CEDI_MacAddress *mask)
1193 {
1194     uint32_t reg;
1195 
1196     if ((pD==NULL) || (mask==NULL))
1197         return EINVAL;
1198     if (CEDI_PdVar(hwCfg).num_spec_add_filters==0)
1199         return ENOTSUP;
1200 
1201     reg = 0;
1202     EMAC_REGS__MASK_ADD1_BOTTOM__ADDRESS_MASK__MODIFY(reg,
1203             mask->byte[0] + (mask->byte[1]<<8) + (mask->byte[2]<<16)
1204                         + (mask->byte[3]<<24));
1205     CPS_UncachedWrite32((CEDI_RegAddr(mask_add1_bottom)), reg);
1206     reg = 0;
1207     EMAC_REGS__MASK_ADD1_TOP__ADDRESS_MASK__MODIFY(reg,
1208             mask->byte[4] + (mask->byte[5]<<8));
1209     CPS_UncachedWrite32((CEDI_RegAddr(mask_add1_top)), reg);
1210     return EOK;
1211 }
1212 
1213 /* Get the value of the specific address 1 mask register
1214  * @param pD - driver private state info specific to this instance
1215  * @param mask - pointer to a 6-byte MAC address struct for returning the
1216  *    mask value
1217  * @return 0 if successful, EINVAL if addrNum invalid
1218  * @return ENOTSUP if CEDI_DesignCfg.num_spec_add_filters==0
1219  */
emacGetSpecificAddr1Mask(void * pD,CEDI_MacAddress * mask)1220 uint32_t emacGetSpecificAddr1Mask(void *pD, CEDI_MacAddress *mask)
1221 {
1222     int reg1, reg2;
1223     if ((pD==NULL)||(mask==NULL)) return EINVAL;
1224     if (CEDI_PdVar(hwCfg).num_spec_add_filters==0)
1225         return ENOTSUP;
1226 
1227     reg1 = EMAC_REGS__MASK_ADD1_BOTTOM__ADDRESS_MASK__READ(
1228             CPS_UncachedRead32(CEDI_RegAddr(mask_add1_bottom)));
1229     reg2 = EMAC_REGS__MASK_ADD1_TOP__ADDRESS_MASK__READ(
1230             CPS_UncachedRead32(CEDI_RegAddr(mask_add1_top)));
1231 
1232 //      vDbgMsg(DBG_GEN_MSG, 10, "top=%08X  bottom=%08X\n", reg2, reg1);
1233     mask->byte[0] = (reg1 & 0xFF);
1234     mask->byte[1] = ((reg1>>8) & 0xFF);
1235     mask->byte[2] = ((reg1>>16) & 0xFF);
1236     mask->byte[3] = ((reg1>>24) & 0xFF);
1237     mask->byte[4] = (reg2 & 0xFF);
1238     mask->byte[5] = ((reg2>>8) & 0xFF);
1239     return EOK;
1240 }
1241 
1242 /* Disable the specific address match stored at given register, by writing 0
1243  * to lower address register
1244  * @param pD - driver private state info specific to this instance
1245  * @param addrNum -
1246  *    number of specific address filters, in range 1 - num_spec_add_filters
1247  *    $RANGE $FROM 1 $TO CEDI_DesignCfg.num_spec_add_filters$
1248  * @return 0 if successful
1249  * @return EINVAL if invalid parameter
1250  * @return ENOTSUP if CEDI_DesignCfg.num_spec_add_filters==0
1251  */
emacDisableSpecAddr(void * pD,uint8_t addrNum)1252 uint32_t emacDisableSpecAddr(void *pD, uint8_t addrNum)
1253 {
1254 #define CEDI_DIS_SPEC_ADDR_CASE(reg) \
1255     case(reg): \
1256         CPS_UncachedWrite32((CEDI_RegAddr(spec_add##reg##_bottom)), 0); break;
1257 
1258     if (!pD) return EINVAL;
1259     if (CEDI_PdVar(hwCfg).num_spec_add_filters==0)
1260         return ENOTSUP;
1261     if ((!addrNum) || (addrNum>(CEDI_PdVar(hwCfg).num_spec_add_filters)))
1262         return EINVAL;
1263 
1264     switch(addrNum) {
1265                 CEDI_DIS_SPEC_ADDR_CASE(1)
1266                 CEDI_DIS_SPEC_ADDR_CASE(2)
1267                 CEDI_DIS_SPEC_ADDR_CASE(3)
1268                 CEDI_DIS_SPEC_ADDR_CASE(4)
1269                 CEDI_DIS_SPEC_ADDR_CASE(5)
1270                 CEDI_DIS_SPEC_ADDR_CASE(6)
1271                 CEDI_DIS_SPEC_ADDR_CASE(7)
1272                 CEDI_DIS_SPEC_ADDR_CASE(8)
1273                 CEDI_DIS_SPEC_ADDR_CASE(9)
1274                 CEDI_DIS_SPEC_ADDR_CASE(10)
1275                 CEDI_DIS_SPEC_ADDR_CASE(11)
1276                 CEDI_DIS_SPEC_ADDR_CASE(12)
1277                 CEDI_DIS_SPEC_ADDR_CASE(13)
1278                 CEDI_DIS_SPEC_ADDR_CASE(14)
1279                 CEDI_DIS_SPEC_ADDR_CASE(15)
1280                 CEDI_DIS_SPEC_ADDR_CASE(16)
1281                 CEDI_DIS_SPEC_ADDR_CASE(17)
1282                 CEDI_DIS_SPEC_ADDR_CASE(18)
1283                 CEDI_DIS_SPEC_ADDR_CASE(19)
1284                 CEDI_DIS_SPEC_ADDR_CASE(20)
1285                 CEDI_DIS_SPEC_ADDR_CASE(21)
1286                 CEDI_DIS_SPEC_ADDR_CASE(22)
1287                 CEDI_DIS_SPEC_ADDR_CASE(23)
1288                 CEDI_DIS_SPEC_ADDR_CASE(24)
1289                 CEDI_DIS_SPEC_ADDR_CASE(25)
1290                 CEDI_DIS_SPEC_ADDR_CASE(26)
1291                 CEDI_DIS_SPEC_ADDR_CASE(27)
1292                 CEDI_DIS_SPEC_ADDR_CASE(28)
1293                 CEDI_DIS_SPEC_ADDR_CASE(29)
1294                 CEDI_DIS_SPEC_ADDR_CASE(30)
1295                 CEDI_DIS_SPEC_ADDR_CASE(31)
1296                 CEDI_DIS_SPEC_ADDR_CASE(32)
1297     }
1298 
1299     return 0;
1300 }
1301 
1302 /**
1303  * En/Disable Type ID match field of the specified register, and set
1304  * type Id value if enabling
1305  * @param[in] pD driver private state info specific to this instance
1306  * @param[in] matchSel number of TypeID Match register, range 1 - 4
1307  *    $RANGE $FROM 1 $TO 4$
1308  * @param[in] typeId the Type ID match value to write,
1309  *    ignored if enable equal 0
1310  * @param[in] enable if equal 1 enables the type matching for this ID,
1311  *    if 0 then disables type matching for this ID
1312  *    $RANGE $FROM 0 $TO 1$
1313  * @return 0 if successful,
1314  * @return EINVAL if matchSel invalid
1315  * $VALIDFAIL if ((enable==0)&&((matchSel<1)||(matchSel>4)))
1316  *  $EXPECT_RETURN EINVAL $
1317  */
emacSetTypeIdMatch(void * pD,uint8_t matchSel,uint16_t typeId,uint8_t enable)1318 uint32_t emacSetTypeIdMatch(void *pD, uint8_t matchSel, uint16_t typeId,
1319         uint8_t enable)
1320 {
1321     uint32_t regVal = 0;
1322     if ((pD==NULL) || (matchSel<1) || (matchSel>4)) return EINVAL;
1323     if (enable>1) return EINVAL;
1324 
1325     switch (matchSel) {
1326     case 1:
1327         if (enable) {
1328             EMAC_REGS__SPEC_TYPE1__ENABLE_COPY__SET(regVal);
1329             EMAC_REGS__SPEC_TYPE1__MATCH__MODIFY(regVal, typeId);
1330         }
1331         CPS_UncachedWrite32(CEDI_RegAddr(spec_type1),regVal);
1332         break;
1333     case 2:
1334         if (enable) {
1335             EMAC_REGS__SPEC_TYPE2__ENABLE_COPY__SET(regVal);
1336             EMAC_REGS__SPEC_TYPE2__MATCH__MODIFY(regVal, typeId);
1337         }
1338         CPS_UncachedWrite32(CEDI_RegAddr(spec_type2),regVal);
1339         break;
1340     case 3:
1341         if (enable) {
1342             EMAC_REGS__SPEC_TYPE3__ENABLE_COPY__SET(regVal);
1343             EMAC_REGS__SPEC_TYPE3__MATCH__MODIFY(regVal, typeId);
1344         }
1345         CPS_UncachedWrite32(CEDI_RegAddr(spec_type3),regVal);
1346         break;
1347     case 4:
1348         if (enable) {
1349             EMAC_REGS__SPEC_TYPE4__ENABLE_COPY__SET(regVal);
1350             EMAC_REGS__SPEC_TYPE4__MATCH__MODIFY(regVal, typeId);
1351         }
1352         CPS_UncachedWrite32(CEDI_RegAddr(spec_type4),regVal);
1353         break;
1354     }
1355 
1356     return 0;
1357 }
1358 
1359 /* Read the specified Type ID match register settings
1360  * @param pD - driver private state info specific to this instance
1361  * @param matchSel  - number of TypeID Match register, range 1 - 4
1362  * @param typeId - pointer for returning the Type ID match value read,
1363  *              ignored if disabled
1364  * @param enabled - pointer for returning enabled status: if value returned <>0
1365  *             then typeId matching is enabled for this register, else disabled
1366  * @return 0 if successful, EINVAL if invalid parameter
1367  */
emacGetTypeIdMatch(void * pD,uint8_t matchSel,uint16_t * typeId,uint8_t * enabled)1368 uint32_t emacGetTypeIdMatch(void *pD, uint8_t matchSel, uint16_t *typeId,
1369         uint8_t *enabled)
1370 {
1371     uint32_t regVal = 0;
1372     if (pD==NULL) return EINVAL;
1373     if ((matchSel<1) || (matchSel>4) || (enabled==NULL)) return EINVAL;
1374     if (*enabled && (typeId==NULL)) return EINVAL;
1375 
1376     switch (matchSel) {
1377     case 1:
1378         regVal = CPS_UncachedRead32(CEDI_RegAddr(spec_type1));
1379         *enabled = EMAC_REGS__SPEC_TYPE1__ENABLE_COPY__READ(regVal);
1380         *typeId = EMAC_REGS__SPEC_TYPE1__MATCH__READ(regVal);
1381         break;
1382     case 2:
1383         regVal = CPS_UncachedRead32(CEDI_RegAddr(spec_type2));
1384         *enabled = EMAC_REGS__SPEC_TYPE2__ENABLE_COPY__READ(regVal);
1385         *typeId = EMAC_REGS__SPEC_TYPE2__MATCH__READ(regVal);
1386         break;
1387     case 3:
1388         regVal = CPS_UncachedRead32(CEDI_RegAddr(spec_type3));
1389         *enabled = EMAC_REGS__SPEC_TYPE3__ENABLE_COPY__READ(regVal);
1390         *typeId = EMAC_REGS__SPEC_TYPE3__MATCH__READ(regVal);
1391         break;
1392     case 4:
1393         regVal = CPS_UncachedRead32(CEDI_RegAddr(spec_type4));
1394         *enabled = EMAC_REGS__SPEC_TYPE4__ENABLE_COPY__READ(regVal);
1395         *typeId = EMAC_REGS__SPEC_TYPE4__MATCH__READ(regVal);
1396         break;
1397     }
1398 
1399     return 0;
1400 }
1401 
1402 /* En/disable reception of unicast frames when hash register matched
1403  * @param pD - driver private state info specific to this instance
1404  * @param enable if<>0, enables reception, else disables
1405  */
emacSetUnicastEnable(void * pD,uint8_t enable)1406 void emacSetUnicastEnable(void *pD, uint8_t enable)
1407 {
1408     uint32_t reg;
1409     if (!pD) return;
1410     if (enable>1) return;
1411     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1412     if (enable)
1413         EMAC_REGS__NETWORK_CONFIG__UNICAST_HASH_ENABLE__SET(reg);
1414     else
1415         EMAC_REGS__NETWORK_CONFIG__UNICAST_HASH_ENABLE__CLR(reg);
1416     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1417 }
1418 
1419 /* Return state of unicast frame matching
1420  * @param pD - driver private state info specific to this instance
1421  * @return  =0 if disabled, =1 if enabled
1422  */
emacGetUnicastEnable(void * pD,uint8_t * enable)1423 uint32_t emacGetUnicastEnable(void *pD, uint8_t *enable)
1424 {
1425     if ((pD==0)||(enable==0))
1426       return EINVAL;
1427     *enable= EMAC_REGS__NETWORK_CONFIG__UNICAST_HASH_ENABLE__READ(
1428             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1429 
1430     return 0;
1431 }
1432 
1433 /* En/disable reception of multicast frames when hash register matched
1434  * @param pD - driver private state info specific to this instance
1435  * @param enable if<>0, enables, else disables
1436  */
emacSetMulticastEnable(void * pD,uint8_t enable)1437 void emacSetMulticastEnable(void *pD, uint8_t enable)
1438 {
1439     uint32_t reg;
1440     if (!pD) return;
1441     if (enable>1) return;
1442     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1443     if (enable)
1444         EMAC_REGS__NETWORK_CONFIG__MULTICAST_HASH_ENABLE__SET(reg);
1445     else
1446         EMAC_REGS__NETWORK_CONFIG__MULTICAST_HASH_ENABLE__CLR(reg);
1447     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1448 }
1449 
1450 /* Return state of multicast frame matching
1451  * @param pD - driver private state info specific to this instance
1452  * @return =0 if disabled, =1 if enabled
1453  */
emacGetMulticastEnable(void * pD,uint8_t * enable)1454 uint32_t emacGetMulticastEnable(void *pD, uint8_t *enable)
1455 {
1456     if ((pD==0)||(enable==0))
1457       return EINVAL;
1458     *enable= EMAC_REGS__NETWORK_CONFIG__MULTICAST_HASH_ENABLE__READ(
1459             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1460 
1461     return 0;
1462 }
1463 
1464 /* Dis/Enable receipt of broadcast frames
1465  * @param pD - driver private state info specific to this instance
1466  * @param reject if =0 broadcasts are accepted, else they are rejected.
1467  */
emacSetNoBroadcast(void * pD,uint8_t reject)1468 void emacSetNoBroadcast(void *pD, uint8_t reject)
1469 {
1470     uint32_t reg;
1471     if (!pD) return;
1472     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1473     if (reject)
1474         EMAC_REGS__NETWORK_CONFIG__NO_BROADCAST__SET(reg);
1475     else
1476         EMAC_REGS__NETWORK_CONFIG__NO_BROADCAST__CLR(reg);
1477     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1478 }
1479 
1480 /* Return broadcast rejection setting
1481  * @param pD - driver private state info specific to this instance
1482  * @return if =0, broadcasts being accepted, else rejected
1483  */
emacGetNoBroadcast(void * pD,uint8_t * reject)1484 uint32_t emacGetNoBroadcast(void *pD, uint8_t *reject)
1485 {
1486     if ((pD==0)||(reject==0))
1487       return EINVAL;
1488     *reject= EMAC_REGS__NETWORK_CONFIG__NO_BROADCAST__READ(
1489             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1490 
1491     return 0;
1492 }
1493 
1494 /* En/Disable receipt of only frames which have been VLAN tagged
1495  * @param pD - driver private state info specific to this instance
1496  * @param enable<>0 to reject non-VLAN-tagged frames.
1497  */
emacSetVlanOnly(void * pD,uint8_t enable)1498 void emacSetVlanOnly(void *pD, uint8_t enable)
1499 {
1500     uint32_t reg;
1501     if (!pD) return;
1502     if (enable>1) return;
1503     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1504     if (enable)
1505         EMAC_REGS__NETWORK_CONFIG__DISCARD_NON_VLAN_FRAMES__SET(reg);
1506     else
1507         EMAC_REGS__NETWORK_CONFIG__DISCARD_NON_VLAN_FRAMES__CLR(reg);
1508     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1509 }
1510 
1511 /* Return VLAN-tagged filter setting
1512  * @param pD - driver private state info specific to this instance
1513  * @return <>0 if VLAN-only, else accept non-VLAN tagged frames
1514  */
emacGetVlanOnly(void * pD,uint8_t * enable)1515 uint32_t emacGetVlanOnly(void *pD, uint8_t *enable)
1516 {
1517     if ((pD==0)||(enable==0))
1518       return EINVAL;
1519     *enable= EMAC_REGS__NETWORK_CONFIG__DISCARD_NON_VLAN_FRAMES__READ(
1520             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1521 
1522     return 0;
1523 }
1524 
1525 /* En/Disable stacked VLAN processing mode.
1526  * @param pD - driver private state info specific to this instance
1527  * @param enable - if <>0 enables stacked VLAN processing, if =0 disables it
1528  * @param vlanType - sets user defined VLAN type for matching first VLAN tag.
1529  *    Ignored if enable =0.
1530  */
emacSetStackedVlanReg(void * pD,uint8_t enable,uint16_t vlanType)1531 void emacSetStackedVlanReg(void *pD, uint8_t enable, uint16_t vlanType)
1532 {
1533     uint32_t reg;
1534     if (!pD) return;
1535     if (enable>1) return;
1536 
1537     reg = CPS_UncachedRead32(CEDI_RegAddr(stacked_vlan));
1538     if (enable) {
1539         EMAC_REGS__STACKED_VLAN__ENABLE_PROCESSING__SET(reg);
1540         EMAC_REGS__STACKED_VLAN__MATCH__MODIFY(reg, vlanType);
1541     }
1542     else
1543         EMAC_REGS__STACKED_VLAN__ENABLE_PROCESSING__CLR(reg);
1544     CPS_UncachedWrite32(CEDI_RegAddr(stacked_vlan), reg);
1545 }
1546 
1547 /* Reads stacked VLAN register settings.
1548  * @param pD - driver private state info specific to this instance
1549  * @param enable - pointer for returning Enabled field: =1 if enabled, =0 if
1550  *    disabled.
1551  * @param vlanType - pointer for returning VLAN type field
1552  *
1553  */
emacGetStackedVlanReg(void * pD,uint8_t * enable,uint16_t * vlanType)1554 void emacGetStackedVlanReg(void *pD, uint8_t *enable, uint16_t *vlanType)
1555 {
1556     uint32_t reg;
1557     if ((pD==NULL)||(enable==NULL) || (vlanType==NULL)) return;
1558 
1559     reg = CPS_UncachedRead32(CEDI_RegAddr(stacked_vlan));
1560     *enable = EMAC_REGS__STACKED_VLAN__ENABLE_PROCESSING__READ(reg);
1561     *vlanType = EMAC_REGS__STACKED_VLAN__MATCH__READ(reg);
1562 }
1563 
1564 /* En/Disable copy all frames mode
1565  * @param pD - driver private state info specific to this instance
1566  * @param enable - if <>0, enables copy all frames mode, else this is
1567  *    disabled
1568  */
emacSetCopyAllFrames(void * pD,uint8_t enable)1569 void emacSetCopyAllFrames(void *pD, uint8_t enable)
1570 {
1571     uint32_t reg;
1572     if (!pD) return;
1573     if (enable>1) return;
1574     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1575     if (enable)
1576         EMAC_REGS__NETWORK_CONFIG__COPY_ALL_FRAMES__SET(reg);
1577     else
1578         EMAC_REGS__NETWORK_CONFIG__COPY_ALL_FRAMES__CLR(reg);
1579     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1580 }
1581 
1582 /* Get "copy all" setting
1583  * @param pD - driver private state info specific to this instance
1584  * @return =0 if disabled, =1 if enabled
1585  */
emacGetCopyAllFrames(void * pD,uint8_t * enable)1586 uint32_t emacGetCopyAllFrames(void *pD, uint8_t *enable)
1587 {
1588     if ((pD==0)||(enable==0))
1589       return EINVAL;
1590     *enable= EMAC_REGS__NETWORK_CONFIG__COPY_ALL_FRAMES__READ(
1591             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1592 
1593     return 0;
1594 }
1595 
1596 /* Set the hash address register.
1597  * @param pD - driver private state info specific to this instance
1598  * @param hAddrTop  -  most significant 32 bits of hash register
1599  * @param hAddrBot  - least significant 32 bits of hash register
1600  * @return EINVAL if pD=NULL, else 0.
1601  */
emacSetHashAddr(void * pD,uint32_t hAddrTop,uint32_t hAddrBot)1602 uint32_t emacSetHashAddr(void *pD, uint32_t hAddrTop, uint32_t hAddrBot)
1603 {
1604     if (pD==NULL) return EINVAL;
1605     CPS_UncachedWrite32(CEDI_RegAddr(hash_bottom),
1606             EMAC_REGS__HASH_BOTTOM__ADDRESS__WRITE(hAddrBot));
1607     CPS_UncachedWrite32(CEDI_RegAddr(hash_top),
1608             EMAC_REGS__HASH_TOP__ADDRESS__WRITE(hAddrTop));
1609     return 0;
1610 }
1611 
1612 /* Read the hash address register.
1613  * @param pD - driver private state info specific to this instance
1614  * @param hAddrTop  -  pointer for returning most significant 32 bits of
1615  *    hash register
1616  * @param hAddrBot  - pointer for returning least significant 32 bits of
1617  *    hash register
1618  * @return EINVAL if any parameter =NULL, else 0.
1619  */
emacGetHashAddr(void * pD,uint32_t * hAddrTop,uint32_t * hAddrBot)1620 uint32_t emacGetHashAddr(void *pD, uint32_t *hAddrTop, uint32_t *hAddrBot)
1621 {
1622     if ((pD==NULL) || (hAddrTop==NULL) || (hAddrBot==NULL)) return EINVAL;
1623     *hAddrBot = EMAC_REGS__HASH_BOTTOM__ADDRESS__READ(
1624                 CPS_UncachedRead32(CEDI_RegAddr(hash_bottom)));
1625     *hAddrTop = EMAC_REGS__HASH_TOP__ADDRESS__READ(
1626                 CPS_UncachedRead32(CEDI_RegAddr(hash_top)));
1627     return 0;
1628 }
1629 
1630 /* Enable/disable discard of frames with length shorter than given in length
1631  * field
1632  * @param pD - driver private state info specific to this instance
1633  * @param enable - if <>1 then enable, else disable.
1634  */
emacSetLenErrDiscard(void * pD,uint8_t enable)1635 void emacSetLenErrDiscard(void *pD, uint8_t enable)
1636 {
1637     uint32_t reg;
1638     if (!pD) return;
1639     if (enable>1) return;
1640     reg = CPS_UncachedRead32(CEDI_RegAddr(network_config));
1641     if (enable)
1642         EMAC_REGS__NETWORK_CONFIG__LENGTH_FIELD_ERROR_FRAME_DISCARD__SET(reg);
1643     else
1644         EMAC_REGS__NETWORK_CONFIG__LENGTH_FIELD_ERROR_FRAME_DISCARD__CLR(reg);
1645     CPS_UncachedWrite32(CEDI_RegAddr(network_config), reg);
1646 }
1647 
1648 /* Read enable/disable status for discard of frames with length shorter than
1649  * given in length field.
1650  * @param pD - driver private state info specific to this instance
1651  * @return 1 if enabled, 0 if disabled.
1652  */
emacGetLenErrDiscard(void * pD,uint8_t * enable)1653 uint32_t emacGetLenErrDiscard(void *pD, uint8_t *enable)
1654 {
1655     if ((pD==0)||(enable==0))
1656       return EINVAL;
1657     *enable= EMAC_REGS__NETWORK_CONFIG__LENGTH_FIELD_ERROR_FRAME_DISCARD__READ(
1658             CPS_UncachedRead32(CEDI_RegAddr(network_config)));
1659 
1660     return 0;
1661 }
1662 
1663 /******************************** Rx Priority Queues ******************************/
1664 
1665 /* Return the numbers of screener, ethtype & compare registers present
1666  * @param pD - driver private state info specific to this instance
1667  * @param regNums - points to a CEDI_NumScreeners struct with the match parameters
1668  *    to be written
1669  * @return 0 if successful, EINVAL if parameter invalid
1670  */
emacGetNumScreenRegs(void * pD,CEDI_NumScreeners * regNums)1671 uint32_t emacGetNumScreenRegs(void *pD, CEDI_NumScreeners *regNums)
1672 {
1673     if ((pD==NULL) || (regNums==NULL))
1674         return EINVAL;
1675 
1676     regNums->type1ScrRegs = CEDI_PdVar(hwCfg).num_type1_screeners;
1677     regNums->type2ScrRegs = CEDI_PdVar(hwCfg).num_type2_screeners;
1678     regNums->ethtypeRegs = CEDI_PdVar(hwCfg).num_scr2_ethtype_regs;
1679     regNums->compareRegs = CEDI_PdVar(hwCfg).num_scr2_compare_regs;
1680     return 0;
1681 }
1682 
1683 
1684 /* Write Rx frame matching values to a Type 1 screening register, for allocating
1685  * to a priority queue.
1686  * @param pD - driver private state info specific to this instance
1687  * @param regNum - the Type 1 register number, range 0 to num_type1_screeners-1
1688  * @param regVals - points to a CEDI_T1Screen struct with the match parameters
1689  *    to be written
1690  * @return 0 if successful, EINVAL if parameter invalid
1691  */
emacSetType1ScreenReg(void * pD,uint8_t regNum,CEDI_T1Screen * regVals)1692 uint32_t emacSetType1ScreenReg(void *pD, uint8_t regNum, CEDI_T1Screen *regVals)
1693 {
1694 #define CEDI_WR_SCRN_TYPE1_REG_CASE(rNum) \
1695     case(rNum):\
1696         CPS_UncachedWrite32(CEDI_RegAddr(screening_type_1_register_##rNum),reg);\
1697         break;
1698 
1699     uint32_t reg;
1700     if ((pD==NULL) || (regVals==NULL))
1701         return EINVAL;
1702 
1703     if (CEDI_PdVar(hwCfg).num_type1_screeners==0)
1704         return ENOTSUP;
1705 
1706     if ((regNum>=CEDI_PdVar(hwCfg).num_type1_screeners) ||
1707         (regVals->qNum>=CEDI_PdVar(cfg).rxQs) ||
1708         (regVals->udpEnable>1) || (regVals->dstcEnable>1))
1709         return EINVAL;
1710 
1711     reg = 0;
1712     EMAC_REGS__SCREENING_TYPE_1_REGISTER__QUEUE_NUMBER__MODIFY(reg,
1713                                                             regVals->qNum);
1714     EMAC_REGS__SCREENING_TYPE_1_REGISTER__DSTC_ENABLE__MODIFY(reg,
1715                                                         regVals->dstcEnable);
1716     EMAC_REGS__SCREENING_TYPE_1_REGISTER__DSTC_MATCH__MODIFY(reg,
1717                                                         regVals->dstcMatch);
1718     EMAC_REGS__SCREENING_TYPE_1_REGISTER__UDP_PORT_MATCH_ENABLE__MODIFY(reg,
1719                                                     regVals->udpEnable);
1720     EMAC_REGS__SCREENING_TYPE_1_REGISTER__UDP_PORT_MATCH__MODIFY(reg,
1721                                                         regVals->udpPort);
1722 
1723     switch (regNum) {
1724         CEDI_WR_SCRN_TYPE1_REG_CASE(0)
1725         CEDI_WR_SCRN_TYPE1_REG_CASE(1)
1726         CEDI_WR_SCRN_TYPE1_REG_CASE(2)
1727         CEDI_WR_SCRN_TYPE1_REG_CASE(3)
1728         CEDI_WR_SCRN_TYPE1_REG_CASE(4)
1729         CEDI_WR_SCRN_TYPE1_REG_CASE(5)
1730         CEDI_WR_SCRN_TYPE1_REG_CASE(6)
1731         CEDI_WR_SCRN_TYPE1_REG_CASE(7)
1732         CEDI_WR_SCRN_TYPE1_REG_CASE(8)
1733         CEDI_WR_SCRN_TYPE1_REG_CASE(9)
1734         CEDI_WR_SCRN_TYPE1_REG_CASE(10)
1735         CEDI_WR_SCRN_TYPE1_REG_CASE(11)
1736         CEDI_WR_SCRN_TYPE1_REG_CASE(12)
1737         CEDI_WR_SCRN_TYPE1_REG_CASE(13)
1738         CEDI_WR_SCRN_TYPE1_REG_CASE(14)
1739         CEDI_WR_SCRN_TYPE1_REG_CASE(15)
1740     }
1741     return 0;
1742 }
1743 
1744 /* Read Rx frame matching values from a Type1 screening register
1745  * @param pD - driver private state info specific to this instance
1746  * @param regNum - the Type 1 register number, range 0 to num_type1_screeners-1
1747  * @param regVals - points to a CEDI_T1Screen struct for returning the match
1748  *    parameters
1749  * @return 0 if successful, EINVAL if parameter invalid
1750  */
emacGetType1ScreenReg(void * pD,uint8_t regNum,CEDI_T1Screen * regVals)1751 uint32_t emacGetType1ScreenReg(void *pD, uint8_t regNum, CEDI_T1Screen *regVals)
1752 {
1753 #define CEDI_RD_SCRN_TYPE1_REG_CASE(rNum) \
1754     case(rNum):\
1755         reg=CPS_UncachedRead32(CEDI_RegAddr(screening_type_1_register_##rNum));\
1756         break;
1757 
1758     uint32_t reg = 0;
1759 
1760     if ((pD==NULL) || (regVals==NULL))
1761         return EINVAL;
1762 
1763     if (CEDI_PdVar(hwCfg).num_type1_screeners==0)
1764         return ENOTSUP;
1765 
1766     if (regNum>=CEDI_PdVar(hwCfg).num_type1_screeners)
1767         return EINVAL;
1768 
1769     switch (regNum) {
1770         CEDI_RD_SCRN_TYPE1_REG_CASE(0)
1771         CEDI_RD_SCRN_TYPE1_REG_CASE(1)
1772         CEDI_RD_SCRN_TYPE1_REG_CASE(2)
1773         CEDI_RD_SCRN_TYPE1_REG_CASE(3)
1774         CEDI_RD_SCRN_TYPE1_REG_CASE(4)
1775         CEDI_RD_SCRN_TYPE1_REG_CASE(5)
1776         CEDI_RD_SCRN_TYPE1_REG_CASE(6)
1777         CEDI_RD_SCRN_TYPE1_REG_CASE(7)
1778         CEDI_RD_SCRN_TYPE1_REG_CASE(8)
1779         CEDI_RD_SCRN_TYPE1_REG_CASE(9)
1780         CEDI_RD_SCRN_TYPE1_REG_CASE(10)
1781         CEDI_RD_SCRN_TYPE1_REG_CASE(11)
1782         CEDI_RD_SCRN_TYPE1_REG_CASE(12)
1783         CEDI_RD_SCRN_TYPE1_REG_CASE(13)
1784         CEDI_RD_SCRN_TYPE1_REG_CASE(14)
1785         CEDI_RD_SCRN_TYPE1_REG_CASE(15)
1786     }
1787     regVals->qNum =
1788             EMAC_REGS__SCREENING_TYPE_1_REGISTER__QUEUE_NUMBER__READ(reg);
1789     regVals->dstcMatch =
1790             EMAC_REGS__SCREENING_TYPE_1_REGISTER__DSTC_MATCH__READ(reg);
1791     regVals->udpPort =
1792             EMAC_REGS__SCREENING_TYPE_1_REGISTER__UDP_PORT_MATCH__READ(reg);
1793     regVals->dstcEnable =
1794             EMAC_REGS__SCREENING_TYPE_1_REGISTER__DSTC_ENABLE__READ(reg);
1795     regVals->udpEnable =
1796             EMAC_REGS__SCREENING_TYPE_1_REGISTER__UDP_PORT_MATCH_ENABLE__READ(
1797                     reg);
1798     return 0;
1799 }
1800 
1801 /* Write Rx frame matching values to a Type 2 screening register, for
1802  * allocating to a priority queue.
1803  * @param pD - driver private state info specific to this instance
1804  * @param regNum - the Type 2 register number, range 0 to num_type2_screeners-1
1805  * @param regVals - points to a CEDI_T2Screen struct with the match
1806  *    parameters to be written
1807  * @return 0 if successful, EINVAL if parameter invalid
1808  */
emacSetType2ScreenReg(void * pD,uint8_t regNum,CEDI_T2Screen * regVals)1809 uint32_t emacSetType2ScreenReg(void *pD, uint8_t regNum, CEDI_T2Screen *regVals)
1810 {
1811 #define CEDI_WR_SCRN_TYPE2_REG_CASE(rNum) \
1812     case(rNum):\
1813         CPS_UncachedWrite32(CEDI_RegAddr(screening_type_2_register_##rNum),\
1814             reg); break;
1815 
1816     uint32_t reg;
1817 
1818     if ((pD==NULL) || (regVals==NULL))
1819         return EINVAL;
1820 
1821     if (CEDI_PdVar(hwCfg).num_type2_screeners==0)
1822         return ENOTSUP;
1823 
1824     if ((regNum>=CEDI_PdVar(hwCfg).num_type2_screeners) ||
1825         (regVals->qNum>=CEDI_PdVar(cfg).rxQs) ||
1826         (regVals->vlanEnable>1) ||
1827         (regVals->vlanEnable && (regVals->vlanPriority>=8)) ||
1828         (regVals->eTypeEnable>1) ||
1829         ((regVals->eTypeEnable) && (regVals->ethTypeIndex>=8)) ||
1830             ((regVals->eTypeEnable) &&
1831               (regVals->ethTypeIndex>=CEDI_PdVar(hwCfg).num_scr2_ethtype_regs)) ||
1832         (regVals->compAEnable>1) ||
1833         ((regVals->compAEnable) && (regVals->compAIndex>=32)) ||
1834             ((regVals->compAEnable) &&
1835               (regVals->compAIndex>=CEDI_PdVar(hwCfg).num_scr2_compare_regs)) ||
1836         (regVals->compBEnable>1) ||
1837         ((regVals->compBEnable) && (regVals->compBIndex>=32)) ||
1838             ((regVals->compBEnable) &&
1839               (regVals->compBIndex>=CEDI_PdVar(hwCfg).num_scr2_compare_regs)) ||
1840         (regVals->compCEnable>1) ||
1841         ((regVals->compCEnable) && (regVals->compCIndex>=32)) ||
1842             ((regVals->compCEnable) &&
1843               (regVals->compCIndex>=CEDI_PdVar(hwCfg).num_scr2_compare_regs)))
1844         return EINVAL;
1845 
1846     reg = 0;
1847     EMAC_REGS__SCREENING_TYPE_2_REGISTER__QUEUE_NUMBER__MODIFY(reg,
1848                                                             regVals->qNum);
1849     EMAC_REGS__SCREENING_TYPE_2_REGISTER__VLAN_ENABLE__MODIFY(reg,
1850                                                     regVals->vlanEnable);
1851     EMAC_REGS__SCREENING_TYPE_2_REGISTER__VLAN_PRIORITY__MODIFY(reg,
1852                                                     regVals->vlanPriority);
1853     EMAC_REGS__SCREENING_TYPE_2_REGISTER__ETHERTYPE_ENABLE__MODIFY(reg,
1854                                                     regVals->eTypeEnable);
1855     EMAC_REGS__SCREENING_TYPE_2_REGISTER__INDEX__MODIFY(reg,
1856                                                     regVals->ethTypeIndex);
1857     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_A_ENABLE__MODIFY(reg,
1858                                                     regVals->compAEnable);
1859     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_A__MODIFY(reg,
1860                                                     regVals->compAIndex);
1861     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_B_ENABLE__MODIFY(reg,
1862                                                     regVals->compBEnable);
1863     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_B__MODIFY(reg,
1864                                                     regVals->compBIndex);
1865     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_C_ENABLE__MODIFY(reg,
1866                                                     regVals->compCEnable);
1867     EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_C__MODIFY(reg,
1868                                                     regVals->compCIndex);
1869 
1870     switch (regNum) {
1871         CEDI_WR_SCRN_TYPE2_REG_CASE(0)
1872         CEDI_WR_SCRN_TYPE2_REG_CASE(1)
1873         CEDI_WR_SCRN_TYPE2_REG_CASE(2)
1874         CEDI_WR_SCRN_TYPE2_REG_CASE(3)
1875         CEDI_WR_SCRN_TYPE2_REG_CASE(4)
1876         CEDI_WR_SCRN_TYPE2_REG_CASE(5)
1877         CEDI_WR_SCRN_TYPE2_REG_CASE(6)
1878         CEDI_WR_SCRN_TYPE2_REG_CASE(7)
1879         CEDI_WR_SCRN_TYPE2_REG_CASE(8)
1880         CEDI_WR_SCRN_TYPE2_REG_CASE(9)
1881         CEDI_WR_SCRN_TYPE2_REG_CASE(10)
1882         CEDI_WR_SCRN_TYPE2_REG_CASE(11)
1883         CEDI_WR_SCRN_TYPE2_REG_CASE(12)
1884         CEDI_WR_SCRN_TYPE2_REG_CASE(13)
1885         CEDI_WR_SCRN_TYPE2_REG_CASE(14)
1886         CEDI_WR_SCRN_TYPE2_REG_CASE(15)
1887     }
1888     return 0;
1889 }
1890 
1891 /* Read Rx frame matching values from a Type 2 screening register
1892  * @param pD - driver private state info specific to this instance
1893  * @param regNum - the Type 2 register number, range 0 to num_type2_screeners-1
1894  * @param regVals - points to a CEDI_T2Screen struct for returning the match
1895  *    parameters
1896  * @return 0 if successful, EINVAL if parameter invalid
1897  */
emacGetType2ScreenReg(void * pD,uint8_t regNum,CEDI_T2Screen * regVals)1898 uint32_t emacGetType2ScreenReg(void *pD, uint8_t regNum, CEDI_T2Screen *regVals)
1899 {
1900 #define CEDI_RD_SCRN_TYPE2_REG_CASE(rNum) \
1901     case(rNum):\
1902         reg=CPS_UncachedRead32(CEDI_RegAddr(screening_type_2_register_##rNum));\
1903         break;
1904 
1905     uint32_t reg = 0;
1906 
1907     if ((pD==0)||(regVals==0))
1908         return EINVAL;
1909 
1910     if (CEDI_PdVar(hwCfg).num_type2_screeners==0)
1911         return ENOTSUP;
1912 
1913     if (regNum>=CEDI_PdVar(hwCfg).num_type2_screeners)
1914         return EINVAL;
1915 
1916     switch (regNum) {
1917         CEDI_RD_SCRN_TYPE2_REG_CASE(0)
1918         CEDI_RD_SCRN_TYPE2_REG_CASE(1)
1919         CEDI_RD_SCRN_TYPE2_REG_CASE(2)
1920         CEDI_RD_SCRN_TYPE2_REG_CASE(3)
1921         CEDI_RD_SCRN_TYPE2_REG_CASE(4)
1922         CEDI_RD_SCRN_TYPE2_REG_CASE(5)
1923         CEDI_RD_SCRN_TYPE2_REG_CASE(6)
1924         CEDI_RD_SCRN_TYPE2_REG_CASE(7)
1925         CEDI_RD_SCRN_TYPE2_REG_CASE(8)
1926         CEDI_RD_SCRN_TYPE2_REG_CASE(9)
1927         CEDI_RD_SCRN_TYPE2_REG_CASE(10)
1928         CEDI_RD_SCRN_TYPE2_REG_CASE(11)
1929         CEDI_RD_SCRN_TYPE2_REG_CASE(12)
1930         CEDI_RD_SCRN_TYPE2_REG_CASE(13)
1931         CEDI_RD_SCRN_TYPE2_REG_CASE(14)
1932         CEDI_RD_SCRN_TYPE2_REG_CASE(15)
1933     }
1934     regVals->qNum =
1935             EMAC_REGS__SCREENING_TYPE_2_REGISTER__QUEUE_NUMBER__READ(reg);
1936     regVals->vlanPriority =
1937             EMAC_REGS__SCREENING_TYPE_2_REGISTER__VLAN_PRIORITY__READ(reg);
1938     regVals->vlanEnable =
1939             EMAC_REGS__SCREENING_TYPE_2_REGISTER__VLAN_ENABLE__READ(reg);
1940     regVals->ethTypeIndex =
1941             EMAC_REGS__SCREENING_TYPE_2_REGISTER__INDEX__READ(reg);
1942     regVals->eTypeEnable =
1943             EMAC_REGS__SCREENING_TYPE_2_REGISTER__ETHERTYPE_ENABLE__READ(reg);
1944     regVals->compAIndex =
1945             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_A__READ(reg);
1946     regVals->compAEnable =
1947             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_A_ENABLE__READ(reg);
1948     regVals->compBIndex =
1949             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_B__READ(reg);
1950     regVals->compBEnable =
1951             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_B_ENABLE__READ(reg);
1952     regVals->compCIndex =
1953             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_C__READ(reg);
1954     regVals->compCEnable =
1955             EMAC_REGS__SCREENING_TYPE_2_REGISTER__COMPARE_C_ENABLE__READ(reg);
1956     return 0;
1957 }
1958 
1959 /* Write the ethertype compare value at the given index in the Ethertype
1960  * registers
1961  * @param pD - driver private state info specific to this instance
1962  * @param index - number of screener Type 2 Ethertype compare register to
1963  *    write, range 0 to num_scr2_ethtype_regs-1
1964  * @param eTypeVal - Ethertype compare value to write
1965  * @return 0 if successful, EINVAL if parameter invalid
1966  */
emacSetType2EthertypeReg(void * pD,uint8_t index,uint16_t eTypeVal)1967 uint32_t emacSetType2EthertypeReg(void *pD, uint8_t index, uint16_t eTypeVal)
1968 {
1969 #define CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(rNum) \
1970     case(rNum):\
1971         CPS_UncachedWrite32(CEDI_RegAddr(screening_type_2_ethertype_reg_##rNum),reg);\
1972         break;
1973 
1974     uint32_t reg;
1975 
1976     if (pD==NULL)
1977         return EINVAL;
1978 
1979     if ((CEDI_PdVar(hwCfg).num_type2_screeners==0) ||
1980             (CEDI_PdVar(hwCfg).num_scr2_ethtype_regs==0))
1981     return ENOTSUP;
1982 
1983     if (index>=CEDI_PdVar(hwCfg).num_scr2_ethtype_regs)
1984         return EINVAL;
1985 
1986     reg = 0;
1987     EMAC_REGS__SCREENING_TYPE_2_ETHERTYPE_REG__COMPARE_VALUE__MODIFY(reg,
1988                                                                     eTypeVal);
1989     switch (index) {
1990         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(0)
1991         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(1)
1992         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(2)
1993         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(3)
1994         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(4)
1995         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(5)
1996         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(6)
1997         CEDI_WR_SCRN_TYPE2_ETHTYPE_REG_CASE(7)
1998     }
1999     return 0;
2000 }
2001 
2002 /* Read the ethertype compare value at the given index in the Ethertype
2003  * registers
2004  * @param pD - driver private state info specific to this instance
2005  * @param index - number of screener Type 2 Ethertype compare register to
2006  *    read, range 0 to num_scr2_ethtype_regs-1
2007  * @param eTypeVal - pointer for returning the Ethertype compare value
2008  * @return 0 if successful, EINVAL if parameter invalid
2009  */
emacGetType2EthertypeReg(void * pD,uint8_t index,uint16_t * eTypeVal)2010 uint32_t emacGetType2EthertypeReg(void *pD, uint8_t index, uint16_t *eTypeVal)
2011 {
2012 #define CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(rNum) \
2013     case(rNum):\
2014         reg = CPS_UncachedRead32(CEDI_RegAddr(screening_type_2_ethertype_reg_##rNum));\
2015         break;
2016 
2017     uint32_t reg = 0;
2018 
2019     if ((pD==NULL)||(eTypeVal==NULL))
2020         return EINVAL;
2021 
2022     if ((CEDI_PdVar(hwCfg).num_type2_screeners==0) ||
2023             (CEDI_PdVar(hwCfg).num_scr2_ethtype_regs==0))
2024     return ENOTSUP;
2025 
2026     if (index>=CEDI_PdVar(hwCfg).num_scr2_ethtype_regs)
2027         return EINVAL;
2028 
2029     switch (index) {
2030         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(0)
2031         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(1)
2032         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(2)
2033         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(3)
2034         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(4)
2035         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(5)
2036         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(6)
2037         CEDI_RD_SCRN_TYPE2_ETHTYPE_REG_CASE(7)
2038     }
2039     *eTypeVal = (uint16_t)(
2040             EMAC_REGS__SCREENING_TYPE_2_ETHERTYPE_REG__COMPARE_VALUE__READ(reg));
2041     return 0;
2042 }
2043 
2044 /* Write the compare value at the given index in the Type 2 compare register
2045  * @param pD - driver private state info specific to this instance
2046  * @param index - number of the Type 2 compare register to write, range 0 to
2047  *    num_scr2_compare_regs-1
2048  * @param regVals - points to a CEDI_T2Compare struct with the compare
2049  *    parameters to be written
2050  * @return 0 if successful, EINVAL if parameter invalid
2051  */
emacSetType2CompareReg(void * pD,uint8_t index,CEDI_T2Compare * regVals)2052 uint32_t emacSetType2CompareReg(void *pD, uint8_t index, CEDI_T2Compare *regVals)
2053 {
2054 #define CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(rNum) \
2055     case(rNum):\
2056         CPS_UncachedWrite32(CEDI_RegAddr(type2_compare_##rNum##_word_0),reg0);\
2057         CPS_UncachedWrite32(CEDI_RegAddr(type2_compare_##rNum##_word_1),reg1);\
2058         break;
2059 
2060     uint32_t reg0, reg1;
2061 
2062     if ((pD==NULL)||(regVals==NULL))
2063         return EINVAL;
2064 
2065     if ((CEDI_PdVar(hwCfg).num_type2_screeners==0) ||
2066             (CEDI_PdVar(hwCfg).num_scr2_compare_regs==0))
2067     return ENOTSUP;
2068 
2069     if ((index>=CEDI_PdVar(hwCfg).num_scr2_compare_regs)
2070         || (regVals->offsetVal>0x3F)
2071         || (regVals->offsetPosition>CEDI_T2COMP_OFF_TCPUDP)
2072         || (regVals->disableMask>1))
2073         return EINVAL;
2074 
2075     reg0 = 0;
2076     reg1 = 0;
2077     EMAC_REGS__TYPE2_COMPARE_WORD_0__MASK_VALUE__MODIFY(reg0,
2078                                                         regVals->compMask);
2079     EMAC_REGS__TYPE2_COMPARE_WORD_0__COMPARE_VALUE__MODIFY(reg0,
2080                                                         regVals->compValue);
2081     EMAC_REGS__TYPE2_COMPARE_WORD_1__OFFSET_VALUE__MODIFY(reg1,
2082                                                         regVals->offsetVal);
2083     EMAC_REGS__TYPE2_COMPARE_WORD_1__COMPARE_OFFSET__MODIFY(reg1,
2084                                                     regVals->offsetPosition);
2085     EMAC_REGS__TYPE2_COMPARE_WORD_1__DISABLE_MASK__MODIFY(reg1,
2086                                                     regVals->disableMask);
2087 
2088     switch (index) {
2089         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(0)
2090         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(1)
2091         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(2)
2092         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(3)
2093         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(4)
2094         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(5)
2095         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(6)
2096         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(7)
2097         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(8)
2098         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(9)
2099         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(10)
2100         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(11)
2101         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(12)
2102         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(13)
2103         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(14)
2104         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(15)
2105         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(16)
2106         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(17)
2107         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(18)
2108         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(19)
2109         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(20)
2110         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(21)
2111         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(22)
2112         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(23)
2113         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(24)
2114         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(25)
2115         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(26)
2116         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(27)
2117         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(28)
2118         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(29)
2119         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(30)
2120         CEDI_WR_SCRN_TYPE2_COMPARE_REG_CASE(31)
2121     }
2122     return 0;
2123 }
2124 
2125 /* Read the compare value at the given index in the Type 2 compare register
2126  * @param pD - driver private state info specific to this instance
2127  * @param index - number of the Type 2 compare register to read, range 0 to
2128  *    num_scr2_compare_regs-1
2129  * @param regVals - points to a CEDI_T2Compare struct for returning the
2130  *    compare parameters
2131  * @return 0 if successful, EINVAL if parameter invalid
2132  */
emacGetType2CompareReg(void * pD,uint8_t index,CEDI_T2Compare * regVals)2133 uint32_t emacGetType2CompareReg(void *pD, uint8_t index, CEDI_T2Compare *regVals)
2134 {
2135 #define CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(rNum) \
2136     case(rNum):\
2137         reg0=CPS_UncachedRead32(CEDI_RegAddr(type2_compare_##rNum##_word_0));\
2138         reg1=CPS_UncachedRead32(CEDI_RegAddr(type2_compare_##rNum##_word_1));\
2139         break;
2140 
2141     uint32_t reg0 = 0, reg1 = 0;
2142 
2143     if ((pD==0)||(regVals==0))
2144       return EINVAL;
2145 
2146     if ((CEDI_PdVar(hwCfg).num_type2_screeners==0) ||
2147             (CEDI_PdVar(hwCfg).num_scr2_compare_regs==0))
2148     return ENOTSUP;
2149 
2150     if (index>=CEDI_PdVar(hwCfg).num_scr2_compare_regs)
2151         return EINVAL;
2152 
2153     switch (index) {
2154         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(0)
2155         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(1)
2156         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(2)
2157         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(3)
2158         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(4)
2159         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(5)
2160         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(6)
2161         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(7)
2162         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(8)
2163         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(9)
2164         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(10)
2165         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(11)
2166         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(12)
2167         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(13)
2168         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(14)
2169         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(15)
2170         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(16)
2171         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(17)
2172         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(18)
2173         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(19)
2174         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(20)
2175         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(21)
2176         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(22)
2177         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(23)
2178         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(24)
2179         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(25)
2180         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(26)
2181         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(27)
2182         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(28)
2183         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(29)
2184         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(30)
2185         CEDI_RD_SCRN_TYPE2_COMPARE_REG_CASE(31)
2186     }
2187 
2188     regVals->compMask =(uint16_t)(
2189         EMAC_REGS__TYPE2_COMPARE_WORD_0__MASK_VALUE__READ(reg0));
2190     regVals->compValue =(uint16_t)(
2191         EMAC_REGS__TYPE2_COMPARE_WORD_0__COMPARE_VALUE__READ(reg0));
2192     regVals->offsetVal =(uint8_t)(
2193         EMAC_REGS__TYPE2_COMPARE_WORD_1__OFFSET_VALUE__READ(reg1));
2194     regVals->offsetPosition =(CEDI_T2Offset)(
2195         EMAC_REGS__TYPE2_COMPARE_WORD_1__COMPARE_OFFSET__READ(reg1));
2196     regVals->disableMask = (uint8_t)(
2197         EMAC_REGS__TYPE2_COMPARE_WORD_1__DISABLE_MASK__READ(reg1));
2198 
2199     return 0;
2200 }
2201 
2202 #ifdef __cplusplus
2203 }
2204 #endif
2205 
2206 #endif /* CY_IP_MXETH */
2207