📄 if_lnisa.c
字号:
ULONG memSize, /* used if memory pool is NOT malloc()'d */ int memWidth, /* byte-width of data (-1 = any width) */ int mode, /* See CONFIG_LNISA in config.h */ int dmaChan /* DMA channel to use */ ) { DRV_CTRL *pDrvCtrl; unsigned int sz; /* temporary size holder */ char *pTurkey; /* start of the LANCE memory pool */ int i;#ifdef IP_ADDR_STORED_IN_EEPROM char ipStr[BOOT_ADDR_LEN]; char *subNetMaskStr; char scratchStr[BOOT_ADDR_LEN]; UINT32 ipAddr = 0; BOOT_PARAMS bootParams;#endif /* IP_ADDR_STORED_IN_EEPROM */ /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return (ERROR); /* * The DMA channel must be one of 5,6 or 7 as it has * to be a 16 bit channel. */ if((dmaChan < 5) || (dmaChan > 7)) return ERROR; /* Ensure single invocation per system life */ pDrvCtrl = & drvCtrl [unit]; if (pDrvCtrl->attached) return (OK); /* * Fill pDrvCtrl->devAdrs out now as it is used by lnCsrXXXX and * lnIdpXXXX functions for register access. */ pDrvCtrl->devAdrs = (LN_DEVICE *)devAdrs; /* LANCE I/O address */ /* set DMA channel to cascade mode to enable device as ISA bus master */ sysOutByte (0xd6,(0xc0 | (dmaChan - 4))); sysOutByte (0xd4,(dmaChan - 4)); /* enable DMA channel */ /* * Examine ISACSR3 for a valid EEPROM. If the EEPROM is invalid bring the * device out of PnP mode using the Software Relocatable key code. This * will allow the user to program the EEPROM with valid information using * the function lnIsa_eeprog(). */ if(lnIdpRead(pDrvCtrl,ISACSR3) != EE_VALID) { printf("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); printf("Ethernet Device EEPROM invalid\n"); printf("Use lnIsa_eeprog(pDrvCtrl,ENET_HI,ENET_MID,ENET_LO");#ifdef IP_ADDR_STORED_IN_EEPROM printf(",\"IP ADDRESS (Dot Notation)\")\n");#else printf("\n");#endif printf("to initialize EEPROM: pDrvCtrl = %p\n",pDrvCtrl); printf("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); lnIsaPnPInitiation(); /* send AMD961 SW relocation key */ lnIsaPnPSetup(devAdrs,(UINT8)ilevel,(UINT8)INT_TYPE_LNISA, (UINT8)dmaChan); for(i = 0; i < 6; i++) lnEnetAddr[i] = 0; /* invalidate enet addr */ return ERROR; } else { /* EEPROM is Valid, so read out the Ethernet Address */ lnCsrWrite(pDrvCtrl,0,4); /* make sure device is stopped */ WR_EE_REG(EE_EN); /* enable EEPROM access */ EE_TIMEOUT; *(UINT16 *)(&lnEnetAddr[4]) = ntohs(lnIsa_eeread16(pDrvCtrl,2)); *(UINT16 *)(&lnEnetAddr[2]) = ntohs(lnIsa_eeread16(pDrvCtrl,1)); *(UINT16 *)(&lnEnetAddr[0]) = ntohs(lnIsa_eeread16(pDrvCtrl,0));#ifdef IP_ADDR_STORED_IN_EEPROM ipAddr = lnIsa_eeread16(pDrvCtrl,EE_WORD_LEN_MIN+1); ipAddr = ipAddr << 16; ipAddr |= lnIsa_eeread16(pDrvCtrl,EE_WORD_LEN_MIN); sprintf(ipStr,"%d.%d.%d.%d",(ipAddr&0x000000ff), ((ipAddr&0x0000ff00)>>8),((ipAddr&0x00ff0000)>> 16), ((ipAddr&0xff000000)>> 24)); if((ipAddr == 0x0) || (ipAddr == 0xffffffff)) { printf("\n\nInvalid IP Address: %s\n\n",ipStr); return ERROR; } if((ipAddr != 0) && (ipAddr != 0xffffffff)) { bootStringToStruct(BOOT_LINE_ADRS, &bootParams); /* get current subnet mask*/ subNetMaskStr = strstr(&bootParams.ead[0],":"); if(subNetMaskStr != NULL) sprintf(scratchStr,"%s%s",ipStr,subNetMaskStr); else sprintf(scratchStr,"%s",ipStr); sprintf(&bootParams.ead[0],"%s",scratchStr); bootStructToString(BOOT_LINE_ADRS, &bootParams); /* update bootline */ }#endif /* IP_ADDR_STORED_IN_EEPROM */ WR_EE_REG(0); /* Disable EEPROM access */ } #ifdef LNISA_DEBUG printf("\ndevAdrs = %p, ivec = %d, ilevel = %d\n",devAdrs,ivec,ilevel); printf("memAdrs = %p, memSize = %x, memWidth = %d\n",memAdrs, memSize, memWidth); printf("Ethernet Address: %02x:%02x:%02x:%02x:%02x:%02x\n",lnEnetAddr[0], lnEnetAddr[1],lnEnetAddr[2],lnEnetAddr[3],lnEnetAddr[4], lnEnetAddr[5]); printf("IP Address = %08x = %s\n",ipAddr,ipStr);#endif /* Publish the interface data record */ ether_attach ( & pDrvCtrl->idr.ac_if, unit, "lnIsa", (FUNCPTR) NULL, (FUNCPTR) lnIoctl, (FUNCPTR) lnOutput, (FUNCPTR) lnReset ); /* Create the transmit semaphore. */ pDrvCtrl->TxSem = semMCreate ( SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE ); if (pDrvCtrl->TxSem == NULL) { printf ("lnIsa: error creating transmitter semaphore\n"); return (ERROR); } { /***** Establish size of shared memory region we require *****/ if ((int) memAdrs != NONE) /* specified memory pool */ { /* * With a specified memory pool we want to maximize * lnRsize and lnTsize */ sz = (memSize - (RMD_SIZ + TMD_SIZ + sizeof (ln_ib))) / ((2 * LN_BUFSIZ) + RMD_SIZ + TMD_SIZ); sz >>= 1; /* adjust for roundoff */ for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1) ; lnTsize = lnRsize; /* lnTsize = lnRsize for convenience */ } /* limit ring sizes to reasonable values */ if (lnRsize < 2) lnRsize = 2; /* 4 buffers is reasonable min */ if (lnRsize > 7) lnRsize = 7; /* 128 buffers is max for chip */ /* limit ring sizes to reasonable values */ if (lnTsize < 2) lnTsize = 2; /* 4 buffers is reasonable min */ if (lnTsize > 7) lnTsize = 7; /* 128 buffers is max for chip */ /* Add it all up */ sz = (sizeof (ln_ib)) + ( ((1 << lnRsize) + 1) * RMD_SIZ ) + (LN_BUFSIZ << lnRsize) + ( ((1 << lnTsize) + 1) * TMD_SIZ ) + (LN_BUFSIZ << lnTsize) + 6; /* allow for alignment adjustment */ } { /***** 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) memAdrs ) { default : /* caller provided memory */ if ( memSize < sz ) /* not enough space */ { printf ( "lnIsa: not enough memory provided\n" ); return ( ERROR ); } pTurkey = memAdrs; /* set the beginning of pool */ /* assume pool is cache coherent, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; 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 ()) { printf ( "lnIsa: device requires cache coherent memory\n" ); return (ERROR); } pTurkey = (char *) cacheDmaMalloc ( sz ); if ((int)pTurkey == NULL) { printf ( "lnIsa: system memory unavailable\n" ); return (ERROR); } /* copy the DMA structure */ pDrvCtrl->cacheFuncs = cacheDmaFuncs; break; } } /* Turkey Carving * -------------- * * LOW MEMORY * * |-------------------------------------| * | The initialization block | * | (sizeof (ln_ib)) | * |-------------------------------------| * | The Rx descriptors | * | (1 << lnRsize) * sizeof (ln_rmd)| * |-------------------------------------| * | The receive buffers | * | (LN_BUFSIZ << lnRsize) | * |-------------------------------------| * | The Tx descriptors | * | (1 << lnTsize) * sizeof (ln_tmd)| * |-------------------------------------| * | The transmit buffers | * | (LN_BUFSIZ << lnTsize) | * |-------------------------------------| */ /* Save some things */ pDrvCtrl->memBase = (char *)((ULONG)pTurkey & 0xffff0000); pDrvCtrl->memWidth = memWidth; pDrvCtrl->bufSize = LN_BUFSIZ; if ((int) memAdrs == NONE) pDrvCtrl->flags |= LS_MEM_ALLOC_FLAG; { /***** Carve up the turkey *****/ /* First let's clean the whole turkey */ bzero ( (char *) pTurkey, (int) sz ); /* carve out initialization block */ pDrvCtrl->ib = (ln_ib *)pTurkey; sz = sizeof (ln_ib); /* size of initialization block */ /* carve out receive message descriptor (RMD) ring structure */ pDrvCtrl->rpo2 = lnRsize; /* remember for lnConfig */ pDrvCtrl->rsize = (1 << lnRsize); /* receive ring size */ /* make it 16 byte aligned */ pDrvCtrl->rring = (ln_rmd *) (((int)pDrvCtrl->ib + sz + 0x0f) & ~0x0f); sz = (1 << lnRsize) * RMD_SIZ; pDrvCtrl->rmd_ring.r_bufs = (char *)((int)pDrvCtrl->rring + sz); sz = (LN_BUFSIZ << lnRsize); /* room for all the receive buffers */ /* carve out transmit message descriptor (TMD) ring structure */ pDrvCtrl->tpo2 = lnTsize; /* remember for lnConfig */ pDrvCtrl->tsize = (1 << lnTsize); /* transmit ring size */ pDrvCtrl->tring = (ln_tmd *) (((int)pDrvCtrl->rmd_ring.r_bufs + sz + 0x0f) & ~0x0f); sz = (1 << lnTsize) * TMD_SIZ; /* carve out transmit buffer space */ pDrvCtrl->tmd_ring.t_bufs = (char *)((int)pDrvCtrl->tring + sz); } /* Save some values */ pDrvCtrl->ivec = ivec; /* interrupt vector */ pDrvCtrl->ilevel = ilevel; /* interrupt level */ pDrvCtrl->devAdrs = (LN_DEVICE *)devAdrs; /* LANCE I/O address */ /* Obtain our Ethernet address and save it */ bcopy ((char *) lnEnetAddr, (char *)pDrvCtrl->idr.ac_enaddr, 6); { /***** Device Initialization *****/ if (lnChipReset (pDrvCtrl) == ERROR) /* reset lance device */ { logMsg ("lnIsa: cannot Reset device:\n",0,0,0,0,0,0); return (ERROR); } if (intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ivec),lnInt,(int)pDrvCtrl) == ERROR) return (ERROR); { /* Initialize all shared memory structures */ ln_rmd *rmd; ln_tmd *tmd; char *buf; ln_ib *ib; ULONG pTemp; int loopy; /* Set up the Rx descriptors */ rmd = pDrvCtrl->rring; /* receive ring */ buf = pDrvCtrl->rmd_ring.r_bufs; for (loopy = 0; loopy < pDrvCtrl->rsize; loopy++) { pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf);/* convert to physical addr */ rmd->rbuf_adr = (USHORT)(pTemp & 0x0000ffff); /* bits 15:00 buf addr */ rmd->rbuf_rmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */ /* neg of buffer byte count */ rmd->rbuf_bcnt = ((RMD2_BCNT_MSK & -(pDrvCtrl->bufSize)) | RMD2_MBO); rmd->rbuf_mcnt = 0; /* no message byte count yet */ rmd->rbuf_rmd1 |= RMD1_OWN; /* buffer now owned by LANCE */ rmd++; /* step to next descriptor */ buf += (pDrvCtrl->bufSize); /* step to the next buffer */ } pDrvCtrl->rindex = 0; /* Setup the Tx descriptors */ tmd = pDrvCtrl->tring; /* transmit ring */ buf = pDrvCtrl->tmd_ring.t_bufs; for (loopy = 0; loopy < pDrvCtrl->tsize; loopy++) { pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS(buf); /* convert to physical addr */ tmd->tbuf_adr = (USHORT) (pTemp & 0x0000ffff); /* bits 15:00 of addr */ tmd->tbuf_tmd1 = (USHORT)((pTemp & 0x00ff0000) >> 16); /* bits 7:0 */ tmd->tbuf_tmd2 = 0; /* no length of Tx Buf yet */ tmd->tbuf_tmd3 = 0; /* clear status bits */ tmd->tbuf_tmd1 |= TMD1_ENP; /* buffer is end of packet */ tmd->tbuf_tmd1 |= TMD1_STP; /* buffer is start of packet */ tmd++; /* step to next descriptor */ buf += (pDrvCtrl->bufSize); /* step to next buffer */ } pDrvCtrl->tindex = pDrvCtrl->dindex = 0; /* Setup the initialization block */ lnIdpWrite(pDrvCtrl,2, (0x100 | (mode & 0x3))); /* set up mode */ ib = pDrvCtrl->ib; ib->lnIBMode = 0; /* chip will be in normal receive mode */ bcopy ((char *)&pDrvCtrl->idr.ac_enaddr[0],&ib->lnIBPadr[0], 6); pTemp =(ULONG)LN_CACHE_VIRT_TO_PHYS(pDrvCtrl->rring);/* point to Rx ring */ ib->lnIBRdraLow = (USHORT)(pTemp & 0x0000ffff); ib->lnIBRdraHigh = (UCHAR)((pTemp & 0x00ff0000) >> 16); ib->lnRLEN = pDrvCtrl->rpo2<<5; pTemp =(ULONG)LN_CACHE_VIRT_TO_PHYS(pDrvCtrl->tring);/* point to Tx ring */ ib->lnIBTdraLow = (USHORT)(pTemp & 0x0000ffff); ib->lnIBTdraHigh = (UCHAR)((pTemp & 0x00ff0000) >> 16); ib->lnTLEN = pDrvCtrl->tpo2<<5; /* Flush the write pipe */ CACHE_PIPE_FLUSH (); } { /* Start the device */ USHORT stat = 0; ULONG pTemp; int timeoutCount = 0; lnCsrWrite (pDrvCtrl, 0, CSR0_STOP); /* set the stop bit */ /* Point the device to the initialization block */ pTemp = (ULONG)LN_CACHE_VIRT_TO_PHYS ( pDrvCtrl->ib ); lnCsrWrite (pDrvCtrl, 2, (USHORT)((pTemp >> 16) & 0x000000ff)); lnCsrWrite (pDrvCtrl, 1, (USHORT)(pTemp & 0x0000ffff)); lnCsrWrite (pDrvCtrl, 0, CSR0_INIT); /* init chip (read IB) */ while (((stat = lnCsrRead (pDrvCtrl, 0)) & (CSR0_IDON | CSR0_ERR)) == 0) { if (timeoutCount++ > 5) break; taskDelay(sysClkRateGet()); } if ((stat & CSR0_ERR) == CSR0_ERR) { if ((stat & CSR0_MERR) == CSR0_MERR) { printf ("Lance Memory error during initialization:\t0x%x\n", stat); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -