📄 lan9118.c
字号:
} if(initString[0] == EOS) { bcopy((char *)DRV_NAME, initString, DRV_NAME_LEN); return NULL; } /* allocate the device structure */ pDrvCtrl = (END_DEVICE *)calloc(sizeof(END_DEVICE), 1); if(pDrvCtrl == NULL) goto errorExit; pDrvCtrl->unit = 0; pDrvCtrl->ilevel = LAN9118_INT_LEVEL; pDrvCtrl->ivec = LAN9118_INT_VECTOR; pDrvCtrl->resetting = FALSE; pDrvCtrl->enetAddr[0] = 0x4000; pDrvCtrl->enetAddr[1] = 0x1b45; pDrvCtrl->enetAddr[2] = 0x0dd2; /* initialize the END and MIB2 parts of the structure * The M2 element must come from m2Lib.h * This lan9118 is set up for a DIX type ethernet device. */ if( (END_OBJ_INIT(&pDrvCtrl->end, (DEV_OBJ*)pDrvCtrl, DRV_NAME, pDrvCtrl->unit, &lan9118FuncTable,DRV_DESC) == ERROR) || (END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd, (UCHAR*)&(pDrvCtrl->enetAddr[0]), 6, ETHERMTU,END_SPEED) == ERROR)) { goto errorExit; } /* Perform memory allocation/distribution */ if(lan9118MemInit(pDrvCtrl) == ERROR) { goto errorExit; } /* reset and reconfigure the device */ lan9118Reset(pDrvCtrl); lan9118Config(pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY(&pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); p_end_device = pDrvCtrl; return (&(pDrvCtrl->end));errorExit: if(p_end_device != NULL) { free((char *)p_end_device); } return NULL;}int get_interrupt = 0;int get_event = 0;/* lan9118_interrupt - lan9118 interrupt process in task level. */STATUS lan9118_interrupt ( END_DEVICE * pDrvCtrl ){ U32 interrupt_status = 0; get_interrupt += 1; /* get the interrupt status. */ interrupt_status = lan9118_reg_read(LAN9118_REG_OFFSET_INT_STS); if (interrupt_status & 0x00000008){ /* some data in rx fifo. */ /* receive. */ lan9118_receive(pDrvCtrl); get_event += 1; } if (interrupt_status & 0x00004000){ /* receive error. */ printf("RX ERROR!!!\n"); get_event += 1; } if (interrupt_status & 0x00002000){ /* transmit error. */ printf("TX ERROR!!!\n"); get_event += 1; } lan9118_reg_write(LAN9118_REG_OFFSET_INT_STS, interrupt_status); return OK;}/* * lan9118Start - start the device * * This function calls BSP functions to connect interrupts and start the * device running in interrupt mode. * * RETURNS: OK or ERROR * */STATUS lan9118Start ( END_DEVICE* pDrvCtrl /* device ID */ ){ int temp_int; ringid_rx = rngCreate(sizeof(struct_end_rx_frame)*1024*4); if (ringid_rx == NULL) { return ERROR; } /* TODO - start the device, enabling interrupts */ /* enable pins for net interrupt. */ lan9118_pin_enable(); /* install isr. */ if(intConnect(INUM_TO_IVEC(pDrvCtrl->ivec), lan9118Int, (int)pDrvCtrl) == ERROR) { return ERROR; } END_FLAGS_SET(&pDrvCtrl->end, IFF_UP | IFF_RUNNING); /* create semaphore for tx. */ semid_lan9118_tx_mux = semBCreate(SEM_Q_FIFO, SEM_FULL); if(semid_lan9118_tx_mux == NULL) { return ERROR; } /* create semaphore for rx. */ pDrvCtrl->semid_rx = semBCreate(SEM_Q_FIFO, SEM_FULL); if(pDrvCtrl->semid_rx == NULL) { semDelete(semid_lan9118_tx_mux); return ERROR; } /* enable interrupt. */ intEnable(pDrvCtrl->ilevel); /* enable interrupt of lan9118. */ /* enable master interrupt, and irq pin. set irq active fall edge. */ lan9118_reg_write(LAN9118_REG_OFFSET_IRQ_CFG, 0x00000101); return OK;}/* * lan9118Send - 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. */STATUS lan9118Send ( END_DEVICE* pDrvCtrl, /* device ptr */ M_BLK_ID pMblk /* data to send */ ){ static UCHAR p_src_buf[END_BUFSIZ]; int old_level = 0; int length = 0; STATUS tx_status = ERROR; semTake(semid_lan9118_tx_mux,WAIT_FOREVER); if(pDrvCtrl->resetting) return END_ERR_BLOCK; END_TX_SEM_TAKE(&pDrvCtrl->end, WAIT_FOREVER); /* Get data from Mblk to tx buffer. */ length = netMblkToBufCopy(pMblk, (char*)p_src_buf, NULL); netMblkClChainFree(pMblk); tx_status = lan9118_send((U32 *)p_src_buf, length); if(tx_status != length) { /* transmit failed. */ printf("END_ERR_BLOCK!!!\n"); semGive(semid_lan9118_tx_mux); return END_ERR_BLOCK; } END_TX_SEM_GIVE(&pDrvCtrl->end); /* Bump the statistics counters. */ END_ERR_ADD(&pDrvCtrl->end, MIB2_OUT_UCAST, +1); semGive(semid_lan9118_tx_mux); return OK;}/* * lan9118Ioctl - the driver I/O control routine * * Process an ioctl request. * * RETURNS: A command specific response, usually OK or ERROR. */int lan9118Ioctl ( 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); } lan9118Config (pDrvCtrl); break; case EIOCGFLAGS: /* get flags */ *(int *)data = END_FLAGS_GET(&pDrvCtrl->end); break; case EIOCPOLLSTART: /* Begin polled operation */ lan9118PollStart(pDrvCtrl); break; case EIOCPOLLSTOP: /* End polled operation */ lan9118PollStop(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 = lan9118_MIN_FBUF; break; case EIOCGHDRLEN: if(data == NULL) return EINVAL; *(int *)data = EH_SIZE; break; default: /* unknown request */ error = EINVAL; } return error;}/* * lan9118PollRcv - routine to receive a packet in polled mode. * * Polled mode operation takes place without any kernel or other OS * services available. Use extreme care to insure that this code does not * call any kernel services. Polled mode is only for WDB system mode use. * Kernel services, semaphores, tasks, etc, are not available during WDB * system mode. * * The WDB agent polls the device constantly looking for new data. Typically * the device has a ring of RFDs to receive incoming packets. This routine * examines the ring for any new data and copies it to the provided mblk. * The concern here is to keep the device supplied with empty buffers at all * time. * * RETURNS: OK upon success. EAGAIN is returned when no packet is available. * A return of ERROR indicates a hardware fault or no support for polled mode * at all. */STATUS lan9118PollRcv ( END_DEVICE* pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* ptr to buffer */ ){ return OK;}/* * lan9118PollSend - routine to send a packet in polled mode. * * Polled mode operation takes place without any kernel or other OS * services available. Use extreme care to insure that this code does not * call any kernel services. Polled mode is only for WDB system mode use. * Kernel services, semaphores, tasks, etc, are not available during WDB * system mode. * * A typical implementation is to set aside a fixed buffer for polled send * operation. Copy the mblk data to the buffer and pass the fixed buffer * to the device. Performance is not a consideration for polled operations. * * An alternate implementation is a synchronous one. The routine accepts * user data but does not return until the data has actually been sent. If an * error occurs, the routine returns EAGAIN and the user will retry the request. * * If the device returns OK, then the data has been sent and the user may free * the associated mblk. The driver never frees the mblk in polled mode. * The calling routine will free the mblk upon success. * * RETURNS: OK upon success. EAGAIN if device is busy or no resources. * A return of ERROR indicates a hardware fault or no support for polled mode * at all. */STATUS lan9118PollSend ( END_DEVICE* pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* packet to send */ ){ return OK;}/* * lan9118MCastAdd - add a multicast address for the device * * This routine adds a multicast address to whatever the driver * is already listening for. It then resets the address filter. * * RETURNS: OK or ERROR. */STATUS lan9118MCastAdd ( END_DEVICE* pDrvCtrl, /* device pointer */ char* pAddress /* new address to add */ ){ int error; if((error = etherMultiAdd(&pDrvCtrl->end.multiList, pAddress)) == ENETRESET) { lan9118Config(pDrvCtrl); } return OK;}/* * lan9118MCastDel - delete a multicast address for the device * * This routine removes a multicast address from whatever the driver * is listening for. It then resets the address filter. * * RETURNS: OK or ERROR. */STATUS lan9118MCastDel ( END_DEVICE* pDrvCtrl, /* device pointer */ char* pAddress /* address to be deleted */ ){ int error; if((error = etherMultiDel(&pDrvCtrl->end.multiList, (char*)pAddress)) == ENETRESET) { lan9118Config(pDrvCtrl); } return OK;}/* * lan9118MCastGet - get the multicast address list for the device * * This routine gets the multicast list of whatever the driver * is already listening for. * * RETURNS: OK or ERROR. */STATUS lan9118MCastGet ( END_DEVICE* pDrvCtrl, /* device pointer */ MULTI_TABLE* pTable /* address table to be filled in */ ){ return(etherMultiGet(&pDrvCtrl->end.multiList, pTable));}/* * lan9118Stop - stop the device * * This function calls BSP functions to disconnect interrupts and stop * the device from operating in interrupt mode. * * RETURNS: OK or ERROR. */STATUS lan9118Stop ( END_DEVICE* pDrvCtrl /* device to be stopped */ ){ END_FLAGS_CLR(&pDrvCtrl->end, IFF_UP | IFF_RUNNING); /* TODO - stop/disable the device. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -