⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_sitsang.c

📁 Intel XScale PXA255 引导Linux的Redboot 版bootloader源代码!
💻 C
字号:
//==========================================================================////      dev/if_sitsang.c////      Ethernet device driver for SMsC LAN91C96 on Sitsang////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    alvin// Contributors: gthomas// Date:         2002-08-30// Purpose:      // Description:  hardware driver for LAN91c96 ethernet//              ////####DESCRIPTIONEND####////==========================================================================// Ethernet device driver#include <redboot.h>#include <pkgconf/system.h>#include <pkgconf/devs_eth_arm_sitsang.h>#ifdef CYGPKG_NET#include <pkgconf/net.h>#include <cyg/kernel/kapi.h>#endif#include <cyg/infra/cyg_type.h>#include <cyg/infra/cyg_ass.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#include <cyg/hal/hal_io.h>#include <cyg/infra/diag.h>#include <cyg/hal/drv_api.h>#include <netdev.h>#include <eth_drv.h>#include "../include/lan91c96API.h"#include "../include/lan91c96.h"#define  lan91c96_BASE SITSANG_LAN91C96_ATTREG #define ETHER_ADDR_LEN 6// Instantiate the interfaces that we have:#define SITSANG_PCR_RW  0x08000000#define SITSANG_BCR_RW  0x08000004#define PXA_OSCR 0x40A00010#define PXA_MSC0 0x48000008LAN91C96_ContextT ctxSLan91c96;               // LAN91c96 device info. structure// eth0ETH_DRV_SC(sitsang_sc0,           0,                 // Driver specific data           "eth0",            // Name for this interface           lan91c96_start,    //Hardware/Software initialzation           lan91c96_stop,     //Cleanup           lan91c96_control,  //Write configuration changes, etc.           lan91c96_can_send, //is the device able to transmit           lan91c96_send,     //take data from redboot and write it to the device and command it to send           lan91c96_recv,     //empty device receive buffer and hand the data to redboot           lan91c96_deliver,  //looks to be related to threading           lan91c96_int,      //poll function and interrupt handling?           lan91c96_int_vector  //    );NETDEVTAB_ENTRY(sitsang_netdev0,                 "sitsang-0",                 sitsang_lan91c96_init, //                &sitsang_sc0);static void lan91c96_int(struct eth_drv_sc *sc);static cyg_interrupt lan91c96_interrupt;static cyg_handle_t  lan91c96_interrupt_handle;#define MAX_PACKET_SIZE 1514char transferBuffer[MAX_PACKET_SIZE] ;static void Delay(int uSec){        int delaytime;        int starttime;        delaytime = (int)(uSec*3.6864);        starttime = *(volatile unsigned long *)PXA_OSCR ;        *(volatile unsigned long *)PXA_OSCR = 0;        while ((*(volatile unsigned long *)PXA_OSCR) < delaytime);}// This ISR is called when the ethernet interrupt occursstatic intlan91c96_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs){    cyg_drv_interrupt_mask(0 /*CYGNUM_HAL_INTERRUPT_EINT3*/); //Does this mask the interrupt???????????????????    return (CYGNUM_HAL_INTERRUPT_ETHERNET);  // Run the DSR}// The deliver function (ex-DSR)  handles the ethernet [logical] processingstatic voidlan91c96_deliver(struct eth_drv_sc *sc){    lan91c96_int(sc);    // Allow interrupts to happen again    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_ETHERNET);    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETHERNET);}static intlan91c96_int_vector(struct eth_drv_sc *sc){    return (CYGNUM_HAL_INTERRUPT_ETHERNET /*Actually need to return the interrupt code*/);}static bool sitsang_lan91c96_init(struct cyg_netdevtab_entry *tab){  int i ;  struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;  cyg_uint8 enaddr[6] ;  unsigned short status = 0 ;  LAN91C96_ContextT *ctxP ;  unsigned short PCR,BCR;  unsigned long MSC0;    PCR = *(volatile unsigned short *) SITSANG_PCR_RW;  PCR |= 0x1<<14 | 0x1<<10; //turn LAN power on  *(volatile unsigned short*) SITSANG_PCR_RW = PCR;     BCR = *(volatile unsigned short *) SITSANG_BCR_RW;   BCR |= 1<<2 | 1<<12;  //turn bus open, and LAN reset   *(volatile unsigned short*) SITSANG_BCR_RW = BCR;   Delay(2000);      BCR = *(volatile unsigned short *) SITSANG_BCR_RW;   BCR &= ~(1<<12);  //clear LAN reset   *(volatile unsigned short*) SITSANG_BCR_RW = BCR;   Delay(100000);    BCR = *(volatile unsigned short *) SITSANG_BCR_RW;   BCR |= (1<<13);  //enable 8-bit mode   *(volatile unsigned short*) SITSANG_BCR_RW = BCR;   MSC0 = *(volatile unsigned long *) PXA_MSC0;   MSC0 &= 0x0000ffff;   MSC0 |= 0x7ff10000;   *(volatile unsigned long *) PXA_MSC0 = MSC0;	    (LAN91C96_ContextT *)(sc->driver_private) = &ctxSLan91c96 ;  ctxSLan91c96.transferBufferP = transferBuffer ;  // Initialize environment, setup interrupt handler  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ETHERNET,                             99, // Priority - what goes here?                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler                             (cyg_ISR_t *)lan91c96_isr,                             (cyg_DSR_t *)eth_drv_dsr, // The logical driver DSR                             &lan91c96_interrupt_handle,                             &lan91c96_interrupt);  cyg_drv_interrupt_attach(lan91c96_interrupt_handle);  cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_ETHERNET);  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETHERNET);  LAN91C96SWInitX((LAN91C96_ContextT *)sc->driver_private,                              (PVOID)SITSANG_LAN91C96_IOREG,                                (PVOID)SITSANG_LAN91C96_ATTREG) ;  // Get the address of the private data  // This is a context structure that contains device specific data	ctxP = sc->driver_private ;  //  Start the hardware  LAN91C96HWSetup(ctxP, 1) ;  // Fill in local MAC address so it can be passed  // to the Redboot infrastructure  enaddr[0] = (cyg_uint8)(ctxP->MACAddress[0]) ;  enaddr[1] = (cyg_uint8)(ctxP->MACAddress[0] >> 8) ;  enaddr[2] = (cyg_uint8)(ctxP->MACAddress[1]) ;  enaddr[3] = (cyg_uint8)(ctxP->MACAddress[1] >> 8) ;  enaddr[4] = (cyg_uint8)(ctxP->MACAddress[2]) ;  enaddr[5] = (cyg_uint8)(ctxP->MACAddress[2] >> 8) ;  // clear the transfer buffer  // this buffer is used to transfer data to/from the hardware	for(i=0; i<MAX_PACKET_SIZE; i++)	{		transferBuffer[i] = 0 ;	}  // initialize the Redboot ethernet driver infrastructure  (sc->funs->eth_drv->init)(sc, enaddr);//printf("5. in function sitsang_lan91c96_init\n");    status -= status ;    return true;}static voidlan91c96_stop(struct eth_drv_sc *sc){}//// This function is called to "start up" the interface.  It may be called// multiple times, even when the hardware is already running.  It will be// called whenever something "hardware oriented" changes and should leave// the hardware ready to send/receive packets.//static voidlan91c96_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){  LAN91C96_ContextT *ctxP = sc->driver_private ;  //call LAN91C96HWSetup(LAN91C96_ContextT *ctxP, BOOL resetFlag)  //LAN91C96HWSetup(ctxP, 1) ;  return ;}//// This routine is called to perform special "control" operations//static intlan91c96_control(struct eth_drv_sc *sc, unsigned long key,               void *data, int data_length){  return(0) ;}//// This routine is called to see if it is possible to send another packet.// It will return non-zero if a transmit is possible, zero otherwise.//static intlan91c96_can_send(struct eth_drv_sc *sc){  unsigned short canSend = 0 ;  UINT16 frameHandle = 0;                   // Page number of allocated frame	static unsigned long canSendCnt = 0 ;  LAN91C96_ContextT *ctxP = (LAN91C96_ContextT *)sc->driver_private ;//	BSPLOG(printf("lan91c96_can_send %d   ", ++canSendCnt)) ;	if(!ctxP->packetSent)	{		return(FALSE) ;	}  canSend = TRUE ;    return (canSend);}//// This routine is called to send data to the hardware.static void lan91c96_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,             int total_len, unsigned long txKey){  /*  sg_list contains a pointer to a buffer and its length.  This buffer      contains the data to be transmitted.  'sg_len' is the length of the      data buffers list.  'total_len' is the total number of bytes of      data to transmit.  */  int i, j;	unsigned int lLength, index ;  LAN91C96_ContextT *ctxP = sc->driver_private ;	unsigned char *pTemp ;  unsigned char *txDataBufferP;	static unsigned long txCnt = 0 ;	txDataBufferP = &transferBuffer[0] ;	index = 0 ;	ctxP->packetSent = 0 ;  ctxP->txKey = txKey ;  ctxP->event = ISQ_TxEvent ;		memset(txDataBufferP, 0, MAX_PACKET_SIZE) ;   // Put data into buffer  for(i=0; i<sg_len; i++)  {		lLength = sg_list[i].len ;		pTemp = (unsigned char *)sg_list[i].buf ;		for(j=0; j<lLength; j++)		{			*txDataBufferP = *pTemp ;			txDataBufferP++ ;			pTemp++ ;		}	}	//if total length is less than 64 bytes, pad the end of the message with zeroes#define MIN_LAN91C96_PACKET_SIZE 64	if(total_len < MIN_LAN91C96_PACKET_SIZE)	{		for(j=total_len; j<MIN_LAN91C96_PACKET_SIZE; j++)		{			*txDataBufferP++ = (unsigned char) 0x0 ;		}					total_len = MIN_LAN91C96_PACKET_SIZE ;	}	LAN91C96TransmitPacket(ctxP, (unsigned short *)transferBuffer, total_len) ;	(sc->funs->eth_drv->tx_done)(sc, ctxP->txKey, 0);//	BSPLOG(printf("lan91c96_send %d\n",++txCnt))  return ;}//// This function is called when a packet has been received.  It's job is// to prepare to unload the packet from the hardware.  Once the length of// the packet is known, the upper layer of the driver can be told.  When// the upper layer is ready to unload the packet, the internal function// 'lan91c96_recv' will be called to actually fetch it from the hardware.//// This function will be called in response to an interrupt/event or due// to polling of the status of the lan91c96//static voidlan91c96_RxEvent(struct eth_drv_sc *sc){  UINT32 len;	unsigned short *l_transferBufferP = (unsigned short *)&transferBuffer ;  LAN91C96_ContextT *ctxP = (LAN91C96_ContextT *)sc->driver_private ;	len = 0 ;	/*	query the device to determine the length of the packet so that space			can be allocated by the Redboot layer amd to store the received packet			in the transfer buffer.	*/  if( LAN91C96ReceivePacket(ctxP, l_transferBufferP, (unsigned int)(MAX_PACKET_SIZE), &len) )	{//		printf("ethernet hardware receive error\n") ;		return ;	}	ctxP->rxPacketLen = len ;  (sc->funs->eth_drv->recv)(sc, len);//printf("end of function sitsang_lan91c96_RxEvent\n");}//// This function is called as a result of the "eth_drv_recv()" call above.// It's job is to actually fetch data for a packet from the transferBuffer of // the device layer to the receive buffers in the Redboot layer once the Redboot layer// memory buffers have been allocated for the packet.  Note that the buffers// may come in pieces, using a scatter-gather list.  This allows for more// efficient processing in the upper layers of the stack.//static voidlan91c96_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){  int			i ;	int			sgBufLen;  UINT16	*sgDataP ; // Redboot layer data buffer	UINT16	*transferBufferP ; // index into transferBuffer ;	LAN91C96_ContextT *ctxP = (LAN91C96_ContextT *)sc->driver_private ;//printf("In lan91c96_recv\n") ;	transferBufferP = (UINT16 *)(&transferBuffer[0]) ;	/*	the following loop cycles through the Redboot layer data buffers */	/*	the loop should continue until the transferBuffer is emptied of valid			data.  The loop will automatically use the number of sg_list indexes			required to hold all of the data retrieved from the hardware	*/  for (i = 0; i < sg_len; i++)	{		sgDataP = (UINT16 *)sg_list[i].buf ;		if(!sgDataP) 		{//			printf("cleanup and get out of here because the system can't handle the message\n") ;			return ;		} 		sgBufLen = sg_list[i].len;				while (sgBufLen >= sizeof(*sgDataP))		{			*sgDataP++ = *(transferBufferP++) ;						sgBufLen -= sizeof(*sgDataP);		}		if (sgBufLen) 		{			// Fetch last odd byte				*(char *)sgDataP = *(char *)transferBufferP & 0xFF ;		}	}//printf("returning from lan91c96_recv\n") ;	return ;}static voidlan91c96_TxEvent(struct eth_drv_sc *sc, int stat){    struct LAN91C96_ContextS *ctxP = (struct LAN91C96_ContextS *)sc->driver_private;    unsigned long status = 0 ; //status of the device      status = ctxP->packetSent ;//printf("2. leaving TxEvent\n") ;    (sc->funs->eth_drv->tx_done)(sc, ctxP->packetSent, 0);//printf("2. leaving TxEvent\n") ;}static voidlan91c96_BufEvent(struct eth_drv_sc *sc, int stat){// not sure this is needed}/*  FUNCTION: lan91c96_int  PURPOSE:  Determines and services interrupts/events  */static voidlan91c96_int(struct eth_drv_sc *sc){	struct LAN91C96_ContextS *ctxP = (struct LAN91C96_ContextS *)sc->driver_private ;	if(LAN91C96ReceiveStatus(ctxP))	{		lan91c96_RxEvent(sc);	}	return ; }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -