📄 templateend.c
字号:
"END Template Driver.") == ERROR || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], 6, END_BUFSIZ, END_SPEED) == ERROR) goto errorExit; /* Perform memory allocation/distribution */ if (templateMemInit (pDrvCtrl) == ERROR) goto errorExit; /* reset and reconfigure the device */ templateReset (pDrvCtrl); templateConfig (pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); DRV_LOG (DRV_DEBUG_LOAD, "Done loading Template...", 1, 2, 3, 4, 5, 6); return (&pDrvCtrl->end);errorExit: if (pDrvCtrl != NULL) free ((char *)pDrvCtrl); return NULL; }/********************************************************************************* templateParse - parse the init string** Parse the input string. Fill in values in the driver control structure.** The muxLib.o module automatically prepends the unit number to the user's* initialization string from the BSP (configNet.h).** .IP <unit>* Device unit number, a small integer.* .IP <vecNum>* Interrupt vector number* .IP <intLvl>* Interrupt level* .LP** RETURNS: OK or ERROR for invalid arguments.*/LOCAL STATUS templateParse ( END_DEVICE * pDrvCtrl, /* device pointer */ char * initString /* information string */ ) { char* tok; char* pHolder = NULL; /* Parse the initString */ /* Unit number. (from muxLib.o) */ tok = strtok_r (initString, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); /* Interrupt vector. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); /* Interrupt level. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ilevel = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugments\n", 1, 2, 3, 4, 5, 6); return OK; }/********************************************************************************* templateMemInit - initialize memory for the chip** This routine is highly specific to the device.** Design choices available:** Use default system buffers, or create device specific buffer pools.** Use contiguous buffers for device frame descriptors and the data, or* use descriptor buffers separate from the data buffers.** Use the same buffering scheme for Rx and Tx, or each side uses it's* own buffering scheme.** RETURNS: OK or ERROR.*/LOCAL STATUS templateMemInit ( END_DEVICE * pDrvCtrl /* device to be initialized */ ) { int count = 0; /* TODO - allocate and initialize any shared memory areas */ /* * This is how we would set up an END netPool using netBufLib(1). * This code is pretty generic. */ if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); /* * Note, Separating the descriptor from the data buffer can be * advantageous for architectures that need cached data buffers but * don't have snooping units to make the caches fully coherent. * It is a disadvantage for architectures that do have snooping, becuase * they need to do twice the number of netBufLib operations for each * data frame. This template driver assumes the descriptor and data * buffer are contiguous. */ /* number of driver Descriptor/data buffers */ templateClDescTbl[0].clNum = 16; /* Setup mbuf/cluster block pool with more mbufs than clBlks */ templateMclBlkConfig.clBlkNum = templateClDescTbl[0].clNum; templateMclBlkConfig.mBlkNum = templateMclBlkConfig.clBlkNum * 4; /* Calculate the total memory for all the M-Blks and CL-Blks. */ templateMclBlkConfig.memSize = (templateMclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) + (templateMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))); /* allocate mbuf/Cluster blocks from normal memory */ if ((templateMclBlkConfig.memArea = (char *) memalign (sizeof(long), templateMclBlkConfig.memSize)) == NULL) return (ERROR); /* Round cluster size up to a multiple of a cache line */ templateClDescTbl[0].clSize = ROUND_UP(templateClDescTbl[0].clSize,_CACHE_ALIGN_SIZE); /* Calculate the memory size of all the clusters. */ templateClDescTbl[0].memSize = (templateClDescTbl[0].clNum * templateClDescTbl[0].clSize); /* Allocate the memory for the clusters from cache safe memory. */ templateClDescTbl[0].memArea = (char *) cacheDmaMalloc (templateClDescTbl[0].memSize); /* cacheDmaMalloc memory is assumed to be cache line aligned ! */ /* use cacheDmaFuncs for cacheDmaMalloc memory */ pDrvCtrl->pCacheFuncs = &cacheDmaFuncs; if (templateClDescTbl[0].memArea == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Initialize the memory pool. */ if (netPoolInit(pDrvCtrl->end.pNetPool, &templateMclBlkConfig, &templateClDescTbl[0], templateClDescTblNumEnt, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* * If you need clusters to store received packets into then get them * here ahead of time. This template driver only uses the cluster pool * for receiving. Here it takes all the clusters out of the pool and * attaches them to the device. The device will fill them with incoming * packets and trigger an interrupt. This will schedule the * templateHandleRcvInt routine. It will unlink the cluster and send * it to the stack. When the stack is done with the data, the cluster * is freed and returned to the cluster pool to be used by the device * again. */ if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool, sizeof (RFD), FALSE)) == NULL) return (ERROR); while (count < templateClDescTbl[0].clNum) { char * pTempBuf; if ((pTempBuf = (char *)netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId)) == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "Could not get a buffer\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* TODO - Store the pointer in some appropriate structure. */ } DRV_LOG (DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6); return OK; }/********************************************************************************* templateStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS templateStart ( END_DEVICE * pDrvCtrl /* device ID */ ) { STATUS result; SYS_INT_CONNECT (pDrvCtrl, templateInt, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); SYS_INT_ENABLE (pDrvCtrl); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING); /* TODO - start the device, enabling interrupts */ return (OK); }/********************************************************************************* templateInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void templateInt ( END_DEVICE *pDrvCtrl /* interrupting device */ ) { UCHAR stat; DRV_LOG (DRV_DEBUG_INT, "Got an interrupt!\n", 1, 2, 3, 4, 5, 6); /* Read the device status register */ stat = templateStatusRead (pDrvCtrl); /* If false interrupt, return. */ if (!(stat & TEMPLATE_VALID_INT)) /* test for valid interrupt */ { return; /* return immediately, no error message */ } /* * enable interrupts, clear receive and/or transmit interrupts, and clear * any errors that may be set. */ /* TODO - Check for errors */ /* Have netTask handle any input packets */ if ((stat & TEMPLATE_RINT) && (stat & TEMPLATE_RXON)) { if (!(pDrvCtrl->rxHandling)) { pDrvCtrl->rxHandling = TRUE; netJobAdd ((FUNCPTR)templateHandleRcvInt, (int)pDrvCtrl, 0,0,0,0); } } /* TODO - handle transmit interrupts */ }/********************************************************************************* templatePacketGet - get next received message** Get next received message. Returns NULL if none are* ready.** RETURNS: ptr to next packet, or NULL if none ready.*/LOCAL PKT* templatePacketGet ( END_DEVICE *pDrvCtrl /* device structure */ ) { /* * TODO - get next received packet. Packet address must be a valid * virtual address, not a physical address. */ return (PKT *)NULL; }/********************************************************************************* templateRecv - process the next incoming packet** Handle one incoming packet. The packet is checked for errors.** RETURNS: N/A.*/LOCAL STATUS templateRecv ( END_DEVICE *pDrvCtrl, /* device structure */ PKT* pPkt /* packet to process */ ) { int len = 0; M_BLK_ID pMblk; char* pCluster = NULL; char* pNewCluster; CL_BLK_ID pClBlk; /* Add one to our unicast data. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* * We implicitly are loaning here, if copying is necessary this * step may be skipped, but the data must be copied before being * passed up to the protocols. */ pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pNewCluster == NULL) { DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } /* Grab a cluster block to marry to the cluster we received. */ if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->end.pNetPool, (UCHAR *)pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, (UCHAR *)pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); /* TODO - Invalidate any RFD dma buffers */ /* TODO - Packet must be checked for errors. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); len = TEMPLATE_PKT_LEN_GET (pPkt); pCluster = TEMPLATE_PKT_VIRT_GET (pPkt); pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* make the packet data coherent */ END_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len); DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6); /* TODO - Done with processing, clean up and pass it up. */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);cleanRXD: return (OK); }/********************************************************************************* templateHandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** The double loop is to protect against a race condition where the interrupt* code see rxHandling as TRUE, but it is then turned off by task code.* This race is not fatal, but does cause occassional delays until a second* packet is received and then triggers the netTask to call this routine again.** RETURNS: N/A.*/LOCAL void templateHandleRcvInt ( END_DEVICE *pDrvCtrl /* interrupting device */ ) { PKT* pPkt; do { pDrvCtrl->rxHandling = TRUE; while ((pPkt = templatePacketGet (pDrvCtrl)) != NULL) templateRecv (pDrvCtrl, pPkt); pDrvCtrl->rxHandling = FALSE; } while (templatePacketGet (pDrvCtrl) != NULL); }/********************************************************************************* templateSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine.** RETURNS: OK, ERROR, or END_ERR_BLOCK.*/LOCAL STATUS templateSend ( END_DEVICE * pDrvCtrl, /* device ptr */ M_BLK_ID pMblk /* data to send */ ) { int oldLevel = 0; BOOL freeNow = TRUE; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & TEMPLATE_POLLING)) END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); /* TODO - Flush the data buffer(s), if it might be cached */ /* TODO - If necessary, get a Tx Frame Descriptor (TFD) */ /* * TODO - If resources are not available, * release the semaphore and return END_ERR_BLOCK. * Do not free packet */ /* TODO - Translate buffer virtual address to a remove bus physical addr */ /* place a transmit request */ if (!(pDrvCtrl->flags & TEMPLATE_POLLING)) oldLevel = intLock (); /* protect templateInt */ /* TODO - initiate device transmit, FLUSH TFD */ /* Advance our management index(es) */ if (!(pDrvCtrl->flags & TEMPLATE_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->end); if (!(pDrvCtrl->flags & TEMPLATE_POLLING)) intUnlock (oldLevel);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -