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