cs8900.c

来自「ADS下的bios工程」· C语言 代码 · 共 669 行 · 第 1/2 页

C
669
字号
int        cs8900_probe (struct netdev *dev);static int cs8900_open (struct netdev *dev);static int cs8900_close (struct netdev *dev);static int cs8900_init (struct netdev *dev);static int cs8900_send (struct netdev *dev, void *buf, int size);static int cs8900_recv (struct netdev *dev, void *buf);/* extern functions */extern int eth_setup (struct netdev *dev);static unsigned short ins( unsigned short offset ){        CSRH_WRITE(CS8900_IO_BASE + DEFAULTIOBASE + ADD_PORT, offset);        return CSRH_READ(CS8900_IO_BASE + DEFAULTIOBASE + DATA_PORT);}static void outs(unsigned short offset, unsigned short value ){        CSRH_WRITE(CS8900_IO_BASE+ DEFAULTIOBASE + ADD_PORT, offset);        CSRH_WRITE(CS8900_IO_BASE + DEFAULTIOBASE + DATA_PORT, value);}static unsigned short readreg( unsigned short offset ){        return CSRH_READ(CS8900_MEM_BASE + offset);}static void writereg(unsigned short offset, unsigned short value ){        CSRH_WRITE(CS8900_MEM_BASE + offset, value);}static void readpkt(int from, short *to, int len){        int i;	volatile unsigned short *sptr;	sptr = (unsigned short *)(CS8900_MEM_BASE + PP_RxFrame);	for(i=0; i<len; i++)		*to++ = *sptr++;}static void writepkt(int to, unsigned short *from, int len){        int i;	volatile unsigned short *dptr;	dptr = (unsigned short *)(CS8900_MEM_BASE + PP_TxFrame);        for(i=0; i<len; i++)		*dptr = *from++;}#ifdef  DEBUG_CS8900static void cs8900_register(unsigned int ioaddr){	if((ins(PP_BusCTL) & MEMORY_ON)) {		printf("\nRead on memory mode\n");	        printf("PP_ChipID  [%x: %x]\n", PP_ChipID, readreg(PP_ChipID));        	printf("PP_RxCFG   [%x: %x]\n", PP_RxCFG, readreg(PP_RxCFG));	        printf("PP_RxCTL   [%x: %x]\n", PP_RxCTL, readreg(PP_RxCTL));        	printf("PP_TxCFG   [%x: %x]\n", PP_TxCFG, readreg(PP_TxCFG));	        printf("PP_TxCMD   [%x: %x]\n", PP_TxCMD, readreg(PP_TxCMD));        	printf("PP_BufCFG  [%x: %x]\n", PP_BufCFG, readreg(PP_BufCFG));	        printf("PP_LineCTL [%x: %x]\n", PP_LineCTL, readreg(PP_LineCTL));        	printf("PP_SelfCTL [%x: %x]\n", PP_SelfCTL, readreg(PP_SelfCTL));	        printf("PP_BusCTL  [%x: %x]\n", PP_BusCTL, readreg(PP_BusCTL));        	printf("PP_TestCTL [%x: %x]\n", PP_TestCTL, readreg(PP_TestCTL));	} else {		printf("\nRead on i/o mode\n");        	printf("PP_ChipID  [%x: %x]\n", PP_ChipID, ins(PP_ChipID));	        printf("PP_RxCFG   [%x: %x]\n", PP_RxCFG, ins(PP_RxCFG));        	printf("PP_RxCTL   [%x: %x]\n", PP_RxCTL, ins(PP_RxCTL));	        printf("PP_TxCFG   [%x: %x]\n", PP_TxCFG, ins(PP_TxCFG));        	printf("PP_TxCMD   [%x: %x]\n", PP_TxCMD, ins(PP_TxCMD));	        printf("PP_BufCFG  [%x: %x]\n", PP_BufCFG, ins(PP_BufCFG));        	printf("PP_LineCTL [%x: %x]\n", PP_LineCTL, ins(PP_LineCTL));	        printf("PP_SelfCTL [%x: %x]\n", PP_SelfCTL, ins(PP_SelfCTL));        	printf("PP_BusCTL  [%x: %x]\n", PP_BusCTL, ins(PP_BusCTL));	        printf("PP_TestCTL [%x: %x]\n", PP_TestCTL, ins(PP_TestCTL));	}}#endifstatic int cs8900_send (struct netdev *dev, void *buf, int size){        volatile struct ei_device *ei = &ei_local; 	int count       ;          /* Transmit packet size */	static char tx_buff[ETH_FRAME_LEN];	unsigned long  flags;        save_flags(flags); cli();	count = (size <= ETH_ZLEN) ? ETH_ZLEN : size;	memcpy (tx_buff, (char *)buf, size);	if ( count != size)	         memset (tx_buff+size, 0, count - size);	/* initiate a transmit sequence */	writereg(PP_TxCommand, TX_AFTER_ALL);	writereg(PP_TxLength, count);	/* Test to see if the chip has allocated memory for the packet */	if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {		/* Gasp!  It hasn't.  But that shouldn't happen since		we're waiting for TxOk, so return 1 and requeue this packet. */		restore_flags(flags);		return 1;	}	/* Write the contents of the packet */	writepkt(PP_TxFrame, (unsigned short *)tx_buff, count>>1);        ei->stats.tx_packets++;	//cs8900_tx_intr(); /* Transmitter, no error */        restore_flags(flags);	return 0;}static int cs8900_receive(void *buf){    volatile struct ei_device *ei = &ei_local;	int status, length;	/* Received Packet status, length */	unsigned char *frame_buff;    length = 0;    frame_buff = (unsigned char *)buf;    status = readreg(PP_RxStatus);    length = readreg(PP_RxLength);		if(!length)		return 0;    length -= 4;	if((status & RX_OK) == 0) {		ei->stats.rx_errors++;		if (status & RX_RUNT) 			ei->stats.rx_length_errors++;		if (status & RX_EXTRA_DATA) 			ei->stats.rx_length_errors++;		if (status & RX_CRC_ERROR) 			if (!(status & (RX_EXTRA_DATA|RX_RUNT)))                ei->stats.rx_crc_errors++;        if (status & RX_DRIBBLE) 			ei->stats.rx_frame_errors++;        return 0;	}	readpkt(PP_RxFrame, (unsigned short *)frame_buff, length>>1);	if(length & 1)		frame_buff[length-1] = readreg(PP_RxFrame);	DEBUG_MAC("RECV_OK: pkt size(%d)\n", length);	ei->stats.rx_packets++;	ei->stats.rx_bytes += length;	return length;}static int cs8900_recv(struct netdev *dev, void *buf){        volatile struct ei_device *ei = &ei_local;	int status, length;	length = 0;	status = readreg(PP_ISQ);	if((status & ISQ_EVENT_MASK) == 0) {		return 0;	}	if((status & ISQ_EVENT_MASK) == ISQ_RX_MISS_EVENT) {		ei->stats.rx_missed_errors++;		return 0;	}	if((status & ISQ_EVENT_MASK) == ISQ_RECEIVER_EVENT) {		DEBUG_MAC("<<RECV GOOD(PKT NO = %d)\n",ei->no++);		length = cs8900_receive(buf); /* Recv. good packets */	}	return length;}static int cs8900_init (struct netdev *dev){     /* Fill the dev fields */     dev->name   = "ETH_CS8900";     dev->open   = &cs8900_open;     dev->close  = &cs8900_close;     dev->send   = &cs8900_send;     dev->recv   = &cs8900_recv;     eth_setup (dev);     return 0;}static int cs8900_open (struct netdev *dev){        volatile struct ei_device *ei = &ei_local;         int i;		/* Assign interrupt number */        outs(PP_INTNUM, CS8900_IRQ_NUM);		/* Change io mode to memory mode */        outs(PP_MEMBASE, 0x1000);	outs(PP_BusCTL, MEMORY_ON);        /* set the Ethernet address */        for (i=0; i < ETH_ALEN/2; i++)                writereg(PP_IA+i*2, dev->hw_addr[i*2] | (dev->hw_addr[i*2+1] << 8));        /* Turn on both receive and transmit operations */        writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);        /* Receive only error free packets addressed to this card */		ei->rx_mode = 0;        writereg(PP_RxCTL, DEF_RX_ACCEPT);        ei->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;        writereg(PP_RxCFG, ei->curr_rx_cfg | BUFFER_CRC);        DEBUG_MAC("PP_RxCFG [%x: %x]\n", PP_RxCFG, readreg(PP_RxCFG));        writereg(PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |               TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);        DEBUG_MAC("PP_TxCFG [%x: %x]\n", PP_TxCFG, readreg(PP_TxCFG));        writereg(PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |                 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);        DEBUG_MAC("PP_BufCFG[%x: %x]\n", PP_BufCFG, readreg(PP_BufCFG));        /* now that we've got our act together, enable everything */        DEBUG_MAC("PP_BusCTL[%x: %x]\n", PP_BusCTL, readreg(PP_BusCTL));        return 0;}static int check_dev_valid(int ioaddr){	/* check device valid, if not return 0 */	/* device is valid, them return io address */	DEBUG_MAC("CS8900_IO_BASE+DEFAULTIOBASE+ADD_PORT = [%x]\n",CS8900_IO_BASE+DEFAULTIOBASE+ADD_PORT);	if(CSRH_READ(CS8900_IO_BASE+DEFAULTIOBASE+ADD_PORT) == ADD_SIG) {	        if(ins(PP_ChipID) == EISA_ID_SIG) {                	        return ioaddr;	        } else {			printf("EISA_ID_SIG(%x)\n", ins(PP_ChipID));			return 0;		}	} else {		printf("ADD_SIG(%x)\n", CSRH_READ(CS8900_IO_BASE+DEFAULTIOBASE+ADD_PORT));		return 0;	}}void reset_chip(void){	int i;	/* Issue a reset command to the chip */	outs(PP_SelfCTL, ins(PP_SelfCTL) | POWER_ON_RESET);	/* Delay for 125 micro-seconds */	for(i=0; i<50*125; i++);	/* Transition SBHE to switch chip from 8-bit to 16-bit */	CSRB_READ(CS8900_IO_BASE + DEFAULTIOBASE + ADD_PORT);	CSRB_READ(CS8900_IO_BASE + DEFAULTIOBASE + ADD_PORT + 1);	CSRB_READ(CS8900_IO_BASE + DEFAULTIOBASE + ADD_PORT);	CSRB_READ(CS8900_IO_BASE + DEFAULTIOBASE + ADD_PORT + 1);	/* Wait until the chip is reset */	for(i=0; i<50*1000*20; i++);		/* 20ms(at least 10ms) */}int cs8900_probe(struct netdev *dev){        volatile struct ei_device *ei = &ei_local;         int ioaddr;        /* Define non-cachable region */	/* Initialize the device structure */        memset((void *)ei, 0, sizeof(struct ei_device));        /* Check device valid */	ioaddr = check_dev_valid(DEFAULTIOBASE);	DEBUG_MAC("ioaddr value is [%d][%x]\n", ioaddr, ioaddr);	if(!ioaddr) {		printf("Check device error\n");		return 1;	}	dev->base_addr = ioaddr;	DEBUG_MAC("Ether probed (0x%3x)\n",dev->base_addr);	/* Reset cs8900 device */	reset_chip();	#ifdef  DEBUG_CS8900	cs8900_register(dev->base_addr); /* read CS8900 all register value for test */#endif        /* Setup Interrupt vector for ZDMA0 */	//set_IrqAction(INT_CS8900, cs8900_interrupt);        //INT_ENABLE(INT_CS8900) ;	DEBUG_MAC("INTMSK(%x)\n", CSR_READ(INTMSK));        cs8900_init(dev);  /* CS8900 device will be initialized */	return 0;}static int cs8900_close (struct netdev *dev){        writereg(PP_SelfCTL, POWER_ON_RESET);	INT_DISABLE(INT_CS8900);	DEBUG_MAC("Shutdown Ethernet...INTMSK(%x)\n", CSR_READ(INTMSK));        return 0;}

⌨️ 快捷键说明

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