📄 rtl81x9.c
字号:
) { UINT sz = 0; /* temporary size holder */ /***** Establish size of shared memory region we require *****/ /*DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9InitMem\n", 0, 0, 0, 0, 0, 0);*/ if ((int) pDrvCtrl->memAdrs != NONE) /* specified memory pool */ { /* * With a specified memory pool we want to maximize * rtlRsize and rtlTsize */ DRV_LOG (DRV_DEBUG_LOAD, "No memAdrs supplied\n", 0, 0, 0, 0, 0, 0); sz = (pDrvCtrl->memSize - (RMD_SIZ + sizeof (rtl_ib))) / ((2 * RTL_BUFSIZ) + RMD_SIZ); sz >>= 1; /* adjust for roundoff */ for (rtlRsize = 0; sz != 0; rtlRsize++, sz >>= 1) ; } /* limit ring sizes to reasonable values */ rtlRsize = max (rtlRsize, 2); /* 4 Rx buffers is reasonable min */ rtlRsize = min (rtlRsize, 7); /* 128 Rx buffers is max for chip */ /* Add it all up */ sz = (((1 << rtlRsize) + 1) * RMD_SIZ) + IB_SIZ + 24; /*DRV_LOG (DRV_DEBUG_LOAD, "sx - %d\n",sz, 0, 0, 0, 0, 0); */ /***** Establish a region of shared memory *****/ /* OK. We now know how much shared memory we need. If the caller * provides a specific memory region, we check to see if the provided * region is large enough for our needs. If the caller did not * provide a specific region, then we attempt to allocate the memory * from the system, using the cache aware allocation system call. */ switch ((int) pDrvCtrl->memAdrs) { default : /* caller provided memory */ if (pDrvCtrl->memSize < sz) /* not enough space */ { DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9: not enough memory provided need %ul got %d\n", pDrvCtrl->memSize, sz, 0, 0, 0, 0); return (NULL); } /* set the beginning of pool */ pDrvCtrl->pShMem = pDrvCtrl->memAdrs; /* assume pool is cache coherent, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; DRV_LOG (DRV_DEBUG_LOAD, "Memory checks out\n",0, 0, 0, 0, 0, 0); break; case NONE : /* get our own memory */ /* Because the structures that are shared between the device * and the driver may share cache lines, the possibility exists * that the driver could flush a cache line for a structure and * wipe out an asynchronous change by the device to a neighboring * structure. Therefore, this driver cannot operate with memory * that is not write coherent. We check for the availability of * such memory here, and abort if the system did not give us what * we need. */ if (!CACHE_DMA_IS_WRITE_COHERENT ()) { DRV_LOG (DRV_DEBUG_LOAD, "rtl: device requires cache coherent memory\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz); if ((int)pDrvCtrl->pShMem == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "rtl: system memory unavailable\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* copy the DMA structure */ pDrvCtrl->cacheFuncs = cacheDmaFuncs; break; } /* Turkey Carving * -------------- * * LOW MEMORY * * |----------------------------------------| * | The initialization block | * | (sizeof (rtl_ib)) | * |----------------------------------------| * | The Rx descriptors | * | ((1 << rtlRsize) + 1)*sizeof (RTL_RMD) | * |----------------------------------------| */ /* align */ pDrvCtrl->pShMem = (char *) ( ( (int)pDrvCtrl->pShMem + 3) & ~3); /* Save some things */ pDrvCtrl->memBase = (char *)((ULONG)pDrvCtrl->pShMem & 0xff000000); if ((int) pDrvCtrl->memAdrs == NONE) pDrvCtrl->flags |= RTL_FLG_MEM_ALLOC_FLAG; /* first let's clear memory */ bzero ((char *) pDrvCtrl->pShMem, (int) sz); /* setup Rx memory pointers */ pDrvCtrl->pRring = (RTL_RMD *) ((int)pDrvCtrl->pShMem + IB_SIZ); pDrvCtrl->rringLen = rtlRsize; pDrvCtrl->rringSize = 1 << rtlRsize; /* Allocate a chunk of memory for the Chip to place the Rx Buffers in */ pDrvCtrl->ptrRxBufSpace = malloc (RTL_RXBUFLEN + 64); pDrvCtrl->ptrRxBufSpace += 4; if (pDrvCtrl->ptrRxBufSpace == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "ptrRxBufSpace == NULL\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pDrvCtrl->rmdNext = 0; /* * Allocate receive buffers from our own private pool. */ if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); rtlMclConfig.mBlkNum = pDrvCtrl->rringSize * 2; rtlClDesc[0].clNum = pDrvCtrl->rringSize *2; rtlMclConfig.clBlkNum = rtlClDesc[0].clNum; rtlMclConfig.memSize = (rtlMclConfig.mBlkNum * (MSIZE + sizeof (long))) + (rtlMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))); if ((rtlMclConfig.memArea = (char *) memalign (sizeof(long), rtlMclConfig.memSize)) == NULL) return (ERROR); rtlClDesc[0].clNum = pDrvCtrl->rringSize *2; rtlClDesc[0].memSize = (rtlClDesc[0].clNum * (RTL_BUFSIZ + 8)) + sizeof(int); if ((int) pDrvCtrl->memAdrs != NONE) /* Do we hand over our own memory? */ { rtlClDesc[0].memArea = (char *)(pDrvCtrl->pRring + (((1 << rtlRsize) + 1) * RMD_SIZ)); } else { rtlClDesc[0].memArea = (char *) cacheDmaMalloc (rtlClDesc[0].memSize); if ((int)rtlClDesc[0].memArea == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } } if (netPoolInit(pDrvCtrl->end.pNetPool, &rtlMclConfig, &rtlClDesc[0], rtlClDescNumEnt, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n",0, 0, 0, 0, 0, 0); return (ERROR); } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, RTL_BUFSIZ, FALSE); return OK; }/********************************************************************************* rtl81x9Start - start the device** This function initializes the device and calls BSP functions to connect* interrupts and start the device running in interrupt mode.** The complement of this routine is rtl81x9Stop. Once a unit is reset by* rtl81x9Stop, it may be re-initialized to a running state by this routine.** RETURNS: OK if successful, otherwise ERROR*/LOCAL STATUS rtl81x9Start ( RTL81X9END_DEVICE * pDrvCtrl ) { STATUS result; int rxcfg; DRV_LOG (DRV_DEBUG_ALL, "RTL81x9 start\n",1 , 2, 3, 4, 5, 6); pDrvCtrl->txBlocked = FALSE; SYS_INT_CONNECT (pDrvCtrl, rtl81x9Int, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; SYS_INT_ENABLE (pDrvCtrl); /* Init the RX buffer pointer register. */ rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, (ULONG) pDrvCtrl->ptrRxBufSpace, RTL_WIN_0); /*DRV_LOG (DRV_DEBUG_ALL, "rxbuffer start- %x: \n",(ULONG) pDrvCtrl->ptrRxBufSpace , 2, 3, 4, 5, 6);*/ /* Enable Tx and RX */ rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0); /* * Set the initial TX and RX configuration. * Set the buffer size and set the wrap register */ rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_CONFIG, RTL_TXCFG_CONFIG, RTL_WIN_0); /* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-TXCFG - %x: \n",RTL_TXCFG_CONFIG , 2, 3, 4, 5, 6);*/ rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_RXCFG_CONFIG, RTL_WIN_0); rxcfg = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_WIN_0); /* Set the Early Threshold bits depending on flags read */ /*vicadd*/ /* from initialisation string */ rxcfg |= ((pDrvCtrl->flags >> 16) << 24); /* Set the individual bit to receive frames for this host only. */ rxcfg |= RTL_RXCG_APM; /* If we want promiscuous mode, set the allframes bit. */ if (pDrvCtrl->ib->rtlIBMode == 0x8000) { rxcfg |= RTL_RXCG_AAP; rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); } else { rxcfg &= ~RTL_RXCG_AAP; rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); } /* * Set capture broadcast bit to capture broadcast frames. */ rxcfg |= RTL_RXCG_AB; /* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-RCR - %x: \n", rxcfg, 2, 3, 4, 5, 6);*/ pDrvCtrl-> reg_rcr =rxcfg;/* save it */ rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); /* We now need to update the Multicast Registers */ /* These values need to be finalised and written */ rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0, 0xffff, RTL_WIN_0); rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0 + 4, 0xffff, RTL_WIN_0); /* Enable Controller Interrupts */ /*vicadd*/ if(pDrvCtrl->flags & RTL_FLG_POLLING) rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0, NONE); else rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE); /* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-IMR - %x: \n",RTL_VALID_INTERRUPTS , 2, 3, 4, 5, 6);*/ /* Start RX/TX process. */ rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_MISSED, 0, RTL_WIN_0); /* Enable Tx and RX */ rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0); return (OK); }/********************************************************************************* rtl81x9Int - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void rtl81x9Int ( RTL81X9END_DEVICE *pDrvCtrl ) { u_short stat; /* Disable controller interrupts. */ rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE); for (;;) { /* Read the interrupt status register */ stat = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE); DRV_LOG (DRV_DEBUG_INT, "ISR %x ", stat,0,0,0,0,0); /* clear interrupts, */ if (stat) rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS, stat, NONE); /* Check if a valid Interrupt has been set */ if ((stat & RTL_VALID_INTERRUPTS) == 0) break; if (stat & RTL_IPT_PCI_ERR) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_PCI_ERR - Reset and Re initialise\n", 0,0,0,0,0,0); rtl81x9Reset (pDrvCtrl); rtl81x9Restart (pDrvCtrl); } if (stat & RTL_IPT_PCS_TIMEOUT) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_PCS_TIMEOUT\n", 0, 0, 0, 0, 0, 0); } if (stat & RTL_IPT_CABLE_LEN_CHG) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_CABLE_LEN_CHG\n", 0, 0, 0, 0, 0, 0); } if (stat & RTL_IPT_RX_FIFO_OVER) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_FIFO_OVER\n", 0, 0, 0, 0, 0, 0); } if (stat & RTL_IPT_RX_UNDERUN) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_UNDERUN\n", 0, 0, 0, 0, 0, 0);/*vicadd*/ rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS, RTL_IPT_RX_OK|RTL_IPT_RX_OVERFLOW|RTL_IPT_RX_FIFO_OVER, NONE); /*rxcfg=rtl81x9CsrReadLong (pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_WIN_0); DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-RCR - %x: \n", rxcfg, 2, 3, 4, 5, 6); */ } if (stat & RTL_IPT_RX_OVERFLOW) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_OVERFLOW\n", 0, 0, 0, 0, 0, 0); } if (stat & RTL_IPT_TX_ERR) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_TX_ERR\n", 0, 0, 0, 0, 0, 0); rtl81x9HandleTxInt (pDrvCtrl); } if (stat & RTL_IPT_RX_ERR) { DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_ERR\n", 0, 0, 0, 0, 0, 0); if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl, 0, 0, 0, 0) != OK) DRV_LOG (DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failed\n", 0, 0, 0, 0, 0, 0); } /* Check for transmit Interrupt */ if (stat & RTL_IPT_TX_OK) { rtl81x9HandleTxInt (pDrvCtrl); } if (stat & RTL_IPT_RX_OK) { if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl, 0, 0, 0, 0) != OK) DRV_LOG (DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failed\n", 0, 0, 0, 0, 0, 0); } } rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE); }/********************************************************************************* rtl81x9HandleTxInt - task level interrupt service for tx packets** This routine is called by the interrupt service routine to do any * message transmission processing.** RETURNS: N/A.*/LOCAL void rtl81x9HandleTxInt ( RTL81X9END_DEVICE *pDrvCtrl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -