📄 cs8900aend.c
字号:
/* Calculate the total memory for all the M-Blks and CL-Blks. */ cs8900aMclBlkConfig.memSize = ((cs8900aMclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) + (cs8900aMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)))); /* allocate mbuf/Cluster blocks from normal memory */ cs8900aMclBlkConfig.memArea = (char *)memalign(sizeof(long),cs8900aMclBlkConfig.memSize); if(cs8900aMclBlkConfig.memArea == NULL)return ERROR; /* Calculate the memory size of all the clusters. */ cs8900aClDescTbl[0].memSize = (cs8900aClDescTbl[0].clNum * (cs8900aClDescTbl[0].clSize + 8)); /* Allocate the memory for the clusters from cache safe memory. */ cs8900aClDescTbl[0].memArea = (char*)cacheDmaMalloc(cs8900aClDescTbl[0].memSize); if(cs8900aClDescTbl[0].memArea == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return ERROR; } /* TODO - allocate and initialize any shared memory areas */ if((pDrvCtrl->end.pNetPool = malloc(sizeof(NET_POOL))) == NULL) return ERROR; /* Initialize the memory pool. */ if(netPoolInit( pDrvCtrl->end.pNetPool, &cs8900aMclBlkConfig, &cs8900aClDescTbl[0], cs8900aClDescTblNumEnt, NULL) == ERROR) { DRV_LOG(DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return ERROR; } DRV_LOG(DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6); return OK;}/* * cs8900aStart - 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 cs8900aStart ( END_DEVICE* pDrvCtrl /* device ID */ ){ /* TODO - start the device, enabling interrupts */ /* enable pins for net interrupt. */ cs8900a_pin_enable(); /* clear any interrupt. */ while(cs_pp_r(pDrvCtrl, CS_PKTPG_ISQ) != 0); cs_chip_int_enable(pDrvCtrl); /* install isr. */ if(intConnect(INUM_TO_IVEC(pDrvCtrl->ivec), cs8900aInt, (int)pDrvCtrl) == ERROR) { return ERROR; } DRV_LOG(DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); /* enable interrupt. */ intEnable(pDrvCtrl->ilevel); /*modified by ddd, enable the eint9 in intmsk*/ DRV_LOG(DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); END_FLAGS_SET(&pDrvCtrl->end, IFF_UP | IFF_RUNNING); return OK;}/* * cs8900aInt - handle controller interrupt * * This routine is called at interrupt level in response to an interrupt from * the controller. * * RETURNS: N/A. */void cs8900aInt(END_DEVICE * pDrvCtrl){ USHORT stat = 0; int recv_len = 0; volatile char * p_char = NULL; volatile char * p_src = (char *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_FRAME); volatile char temp_char1, temp_char2; int i; UINT32 tempUINT32; /* Read pending interrupt and clear it */ s3c2410x_INT_REG_READ(rEINTPND, tempUINT32); /*check if it's eint9*/ if (tempUINT32 & (1<<9)) printf("EINT9 triggered\n"); /*clear the flag*/ s3c2410x_INT_REG_WRITE(rEINTPND, tempUINT32); DRV_LOG(DRV_DEBUG_INT, "Got an interrupt!\n", 1, 2, 3, 4, 5, 6); while(1) { /* Read the device status register */ stat = *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_ISQ)); if(stat == 0) break; switch(stat & CS_REG_NUM_MASK) { case CS_REG_NUM_RX_EVENT: if(CS_RX_EVENT_CRC_ERR & stat) { if(display_net_event) printf("recv-data CRC error!\n"); cs_chip_rx_frame_drop(pDrvCtrl, 1); break; } if(CS_RX_EVENT_RUNT & stat) { if(display_net_event) printf("error, recv-data too short!\n"); cs_chip_rx_frame_drop(pDrvCtrl, 1); break; } if(CS_RX_EVENT_X_DATA & stat) { if(display_net_event) printf("error, recv-data too long!\n"); cs_chip_rx_frame_drop(pDrvCtrl, 1); break; } if(CS_RX_EVENT_RX_OK & stat) { pDrvCtrl->rxHandling = TRUE; p_char = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]); if(p_char != NULL) { recv_len = cs_pp_r(pDrvCtrl, CS_PKTPG_RX_LENGTH); bcopyBytes((char *)p_src, (char *)(p_char + 2), recv_len); /* for(i = 0; i < recv_len; i++) { temp_char1 = p_src[i]; while((temp_char1 & 0x40)&&(i < (recv_len - 4))&&(i < 80)) { temp_char2 = p_src[i]; if(temp_char1 == temp_char2) break; temp_char1 = temp_char2; } p_char[i+2] = temp_char1; } *//*modified by ddd, 2008-7-12 recv_len should not be plused with 2*//* recv_len += 2;*/ } /* netJobAdd ((FUNCPTR)cs8900aHandleRcvInt, (int)pDrvCtrl, (int)p_char,recv_len,0,0); */ netJobAdd ((FUNCPTR)cs8900aRecv, (int)pDrvCtrl, (int)p_char,recv_len,0,0); } break; case CS_REG_NUM_TX_EVENT: if(CS_TX_EVENT_JABBER & stat); if(CS_TX_EVENT_LOSS_CRS & stat); if(CS_TX_EVENT_OUT_WIN & stat); if(CS_TX_EVENT_SQE_ERR & stat); if(CS_TX_EVENT_TX_OK & stat) { if(display_net_event) printf("tx_ok\n"); } break; case CS_REG_NUM_BUF_EVENT: break; case CS_REG_NUM_RX_MISS: if(display_net_event) printf("Warning, net-rx miss!\n"); break; case CS_REG_NUM_TX_COL: if(display_net_event) printf("Warning, net-tx collision!\n"); break; default:; } } return ;}/* * cs8900aRecv - process the next incoming packet * * Handle one incoming packet. The packet is checked for errors. * * RETURNS: N/A. */LOCAL void cs8900aRecv ( END_DEVICE * pDrvCtrl, /* device structure */ char* pNewCluster, int len ){ char * temp_buf = NULL; int temp_count = 0; M_BLK_ID pMblk; CL_BLK_ID pClBlk; int i = 0; pDrvCtrl->rxHandling = TRUE; /* TODO - Packet must be checked for errors. */ 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. */ /* 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) ||(len <= 0)) { 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, pNewCluster, len, NULL, 0, 0, 0); netMblkClJoin(pMblk, pClBlk); /* TODO - Invalidate any RFD dma buffers */ pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; pMblk->mBlkHdr.mData += 2; 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: pDrvCtrl->rxHandling = FALSE; return;}/* * cs8900aSend - 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 cs8900aSend ( END_DEVICE* pDrvCtrl, /* device ptr */ M_BLK_ID pMblk /* data to send */ ){ static UCHAR p_src_buf[CS_CHIP_FRAME_BUF_SIZE]; int old_level = 0; int length = 0; STATUS tx_status = ERROR; if(pDrvCtrl->resetting) return END_ERR_BLOCK; if(!(pDrvCtrl->flags & cs8900a_POLLING)) { END_TX_SEM_TAKE(&pDrvCtrl->end, WAIT_FOREVER); } /* Get data from Mblk to tx buffer. */ length = netMblkToBufCopy(pMblk, (char*)p_src_buf, NULL); /* lock interrupt. */ if(!(pDrvCtrl->flags & cs8900a_POLLING)) { old_level = intLock(); } /* transmit it. */ tx_status = cs_chip_send_frame(pDrvCtrl, (USHORT *)p_src_buf, length); /* unlock interrupt. */ if(!(pDrvCtrl->flags & cs8900a_POLLING)) { intUnlock (old_level); } if(!(pDrvCtrl->flags & cs8900a_POLLING)) { END_TX_SEM_GIVE(&pDrvCtrl->end); } /* Bump the statistics counters. */ END_ERR_ADD(&pDrvCtrl->end, MIB2_OUT_UCAST, +1); if(tx_status == ERROR) { /* transmit failed. */ return END_ERR_BLOCK; } /* * Cleanup. If the driver copied the data from the mblks to a different * buffer, then free the mblks now. Otherwise, free the mblk chain * after the device is finished with the TFD. */ netMblkClChainFree(pMblk); return OK;}/* * cs8900aIoctl - the driver I/O control routine * * Process an ioctl request. * * RETURNS: A command specific response, usually OK or ERROR. */LOCAL int cs8900aIoctl ( END_DEVICE* pDrvCtrl, /* device receiving command */ int cmd, /* ioctl command code */ caddr_t data /* command argument */ ){ int error = 0; long value; switch((unsigned)cmd) { case EIOCSADDR: /* set MAC address */ if (data == NULL) return EINVAL; bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end), END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCGADDR: /* get MAC address */ if(data == NULL) return EINVAL; bcopy((char *)END_HADDR(&pDrvCtrl->end), (char *)data, END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCSFLAGS: /* set (or clear) flags */ value = (long)data; if(value < 0) { value = -value; value--; END_FLAGS_CLR(&pDrvCtrl->end, value); } else { END_FLAGS_SET(&pDrvCtrl->end, value); } cs8900aConfig (pDrvCtrl); break; case EIOCGFLAGS: /* get flags */ *(int *)data = END_FLAGS_GET(&pDrvCtrl->end); break; case EIOCPOLLSTART: /* Begin polled operation */ cs8900aPollStart(pDrvCtrl); break; case EIOCPOLLSTOP: /* End polled operation */ cs8900aPollStop(pDrvCtrl); break; case EIOCGMIB2233: case EIOCGMIB2: /* return MIB information */ if(data == NULL) return EINVAL; bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data, sizeof(pDrvCtrl->end.mib2Tbl)); break; case EIOCGFBUF: /* return minimum First Buffer for chaining */ if(data == NULL) return EINVAL; *(int *)data = cs8900a_MIN_FBUF; break; case EIOCGHDRLEN: if(data == NULL) return EINVAL; *(int *)data = EH_SIZE; break; default: /* unknown request */ error = EINVAL; } return error;}/* * cs8900aConfig - reconfigure the interface under us. * * Reconfigure the interface setting promiscuous mode, and changing the * multicast interface list. * * RETURNS: N/A. */LOCAL void cs8900aConfig ( END_DEVICE* pDrvCtrl /* device to be re-configured */ ){ /*Added by ddd to test */ USHORT data; /* Set promiscuous mode if it's asked for. */ if(END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { DRV_LOG(DRV_DEBUG_IOCTL, "Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6); } else { DRV_LOG(DRV_DEBUG_IOCTL, "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6); } /* Set up address filter for multicasting. */ if(END_MULTI_LST_CNT(&pDrvCtrl->end) > 0) { cs8900aAddrFilterSet(pDrvCtrl); } /* TODO - initialise the hardware according to flags */ cs_pp_w(pDrvCtrl, CS_PKTPG_IO_BASE, pDrvCtrl->io_addr); /* io base. */ cs_pp_w(pDrvCtrl, CS_PKTPG_MEM_BASE, (USHORT)((pDrvCtrl->mem_addr)&0xFFFF)); /* memory base.*/ cs_pp_w(pDrvCtrl, CS_PKTPG_MEM_BASE+2, (USHORT)((pDrvCtrl->mem_addr)>>16)); cs_pp_w(pDrvCtrl, CS_PKTPG_INT_NUM, pDrvCtrl->chip_int_num); /* interrupt pin. */ cs_pp_w(pDrvCtrl, CS_PKTPG_DMA_NUM, pDrvCtrl->chip_dma_num); /* Turn off the dma. */ cs_chip_to_mem_mode(pDrvCtrl, 1); cs_chip_event_enable(pDrvCtrl); /* receive style. */ /* modified by ddd, 711-1621 cs_pp_w(pDrvCtrl, CS_PKTPG_RX_CTL, CS_RX_CTL_RX_OK_A | CS_RX_CTL_ALL_FRAME_A | CS_RX_CTL_BCAST_A | CS_RX_CTL_IND_A); */ /*Added by ddd, Only accept rxok, hash pass packet and individual packet*/ cs_pp_w(pDrvCtrl, CS_PKTPG_RX_CTL, CS_RX_CTL_RX_OK_A | CS_RX_CTL_BCAST_A | CS_RX_CTL_IND_A|0x0003); /* select 10baseT, and turn on rx/tx.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -