📄 smc91113.c
字号:
SMC_outw( PTR_AUTOINC , PTR_REG );// PRINTK3("%s: Trying to xmit packet of length %x\n",// SMC_DEV_NAME, length);#if SMC_DEBUG > 2// printf("Transmitting Packet\n");// print_packet( buf, length );#endif /* send the packet length ( +6 for status, length and ctl byte ) and the status word ( set to zeros ) set by CSMA/CD */#ifdef USE_32_BIT SMC_outl( (length +6 ) << 16 , DATA_REG ); //not use.#else SMC_outw( 0, DATA_REG ); //satus word fill 0. /* send the packet length ( +6 for status words, length, and ctl*/ SMC_outw( (length+6), DATA_REG ); //写缓冲区第二个字地址的内容,这里假设length 是偶数;#endif /* send the actual data . I _think_ it's faster to send the longs first, and then . mop up by sending the last word. It depends heavily . on alignment, at least on the 486. Maybe it would be . a good idea to check which is optimal? But that could take . almost as much time as is saved? */#ifdef USE_32_BIT SMC_outsl(DATA_REG, buf, length >> 2 ); if ( length & 0x2 ) SMC_outw(*((word *)(buf + (length & 0xFFFFFFFC))), DATA_REG);#else SMC_outsw(DATA_REG , buf, (length ) >> 1); //注意,buf指针是指向字节数据的,word number del by xu. #endif // USE_32_BIT /* Send the last byte, if there is one. */ if ( (length & 1) == 0 ) { //even ,last is0. SMC_outw( 0, DATA_REG ); } else { SMC_outw( buf[length -1 ] | 0x2000, DATA_REG ); //odd } /* and let the chipset deal with it */ SMC_outw( MC_ENQUEUE , MMU_CMD_REG ); // return 0; //add byxu . /* poll for TX INT */// if (poll4int(IM_TX_INT, SMC_TX_TIMEOUT)) { //3 if(0){ /* sending failed */// PRINTK2("%s: TX timeout, sending failed...\n",// SMC_DEV_NAME); /* release packet */ SMC_outw(MC_FREEPKT, MMU_CMD_REG); //TX Fail :Release packet in PNR register /* wait for MMU getting ready (low) */ while (SMC_inw(MMU_CMD_REG) & MC_BUSY) { udelay(10); }// PRINTK2("MMU ready\n"); return 0; } else { //read the TX FIFO Packet Number from the FIFO Ports Reg. temp1=read(0x4); //read tx fifo ports register. temp1=temp1&0x3f; //get the tx fifo packet number. temp0=temp1; write(0x2,temp0); //write to pakcket number reg. udelay(100); write(0x0,0xa); //free specific packet. //*pter=0x2; //ack int. /* ack. int */ SMC_outw(IM_TX_INT, INT_REG); //Remove packet number from completion FIFO by writing TX INT Acknowledge Reg.// PRINTK2("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); /* release packet */// SMC_outw(MC_FREEPKT, MMU_CMD_REG); //after read completion status. del by xu. /* wait for MMU getting ready (low) */ while (SMC_inw(MMU_CMD_REG) & MC_BUSY) { udelay(10); }// PRINTK2("MMU ready\n"); } return length;}/*------------------------------------------------------------------------- | | smc_destructor( struct net_device * dev ) | Input parameters: | dev, pointer to the device structure | | Output: | None. | ---------------------------------------------------------------------------*/void smc_destructor(){// PRINTK2(CARDNAME ":smc_destructor\n");}/* * Open and Initialize the board * * Set up everything, reset the card, etc .. * */static int smc_open(){ int i; /* used to set hw ethernet address */// PRINTK2("%s:smc_open\n", SMC_DEV_NAME); /* detect the chip*/ SMC_SELECT_BANK( 3 );// if (SMC_inw( REV_REG ) != 0x3391)// PRINTK2("%s:smc_not exist.\n", SMC_DEV_NAME); /* reset the hardware */ smc_reset(); smc_enable(); /* Configure the PHY */#ifndef CONFIG_SMC91113_EXT_PHY smc_phy_configure(); //配置物理寄存器#endif /* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */// SMC_SELECT_BANK(0);// SMC_outw(0, RPC_REG); SMC_SELECT_BANK( 1 );#ifdef USE_32_BIT for ( i = 0; i < 6; i += 2 ) { word address; address = smc_mac_addr[ i + 1 ] << 8 ; address |= smc_mac_addr[ i ]; SMC_outw( address, ADDR0_REG + i ); }#else for ( i = 0; i < 6; i ++ ) SMC_outb( smc_mac_addr[i], ADDR0_REG + i );#endif return 0;}#ifdef USE_32_BITvoidinsl32(r,b,l) { int __i ; dword *__b2; __b2 = (dword *) b; for (__i = 0; __i < l; __i++) { *(__b2 + __i) = *(dword *)(r+0x10000300); } }#endif#if (SMC_DEBUG > 6 )static void print_sw(l){ int __i; word b2; SMC_outw( PTR_READ | PTR_RCV | 0, PTR_REG ); l += 2; l = l >> 1; // printf("\nQinwei dump package \n "); for (__i = 0; __i < l; __i++) { char a,b; SMC_outw( PTR_READ | PTR_RCV | (__i*2), PTR_REG ); b2 = SMC_inw(DATA_REG); SMC_inw(0); a = (char) b2; b = (char) (b2 >> 8);// printf("%02x %02x ", a, b ); }}#endif/*------------------------------------------------------------- . . smc_rcv - receive a packet from the card . . There is ( at least ) a packet waiting to be read from . chip-memory. . . o Read the status . o If an error, record it . o otherwise, read in the packet --------------------------------------------------------------*/int smc_rcv() //static is del by xu.{ unsigned short packet_number; unsigned short status; unsigned short packet_length; unsigned short temp; byte *pointer; unsigned short temp1,temp2,temp3,temp4,temp5; unsigned short i,k; word NetRxPackets[MAX_LENGTH/2]; byte NetRxPacketb[MAX_LENGTH]; word *datapt0; byte ReceivePackets[MAX_LENGTH],int_number; byte t1=0,t2=0,t3=0,t4=0,t5=0,t6=0,t7=0,t8=0,t9=0,t10=0,t11=0,t12=0; byte t13=0,t14=0,t15=0,t16=0,t17=0,t18=0,t19=0,t20=0,t21=0,t22=0; word t23=0,t24=0,t25=0,t26=0,t27=0,t28=0,t29=0,t30=0,t31=0; int is_error = 0;// pointer = (byte *)0X2000308;#ifdef USE_32_BIT dword stat_len;#endif SMC_SELECT_BANK(2); packet_number = SMC_inw( RXFIFO_REG ); //read FIFO ports reg and get the packet number. int_number = SMC_inb( IM_REG ); //add by xu. if ( packet_number & RXFIFO_REMPTY ) //check the rx fifo empty or not. { if ( int_number & IM_RCV_INT ) //add by xu. { return 0; //not ready ,exit. } return 0; } Led_Display(5);// Delay(2000);// PRINTK3("%s:smc_rcv\n", SMC_DEV_NAME); /* start reading from the start of the packet */ SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG );// temp = SMC_inw(0); /* Qinwei for some delay, 04.01.08 .take mmu command reg.*/ //del by xu. udelay(1); //added by xu. to compansate the upper delay. /* SMC_outw( PTR_READ | PTR_RCV | 0, PTR_REG ); status = SMC_inw( DATA_REG );*/ // (Qinwei temp use, can remove. 03.01.08) /* First two words are status and packet_length */#ifdef USE_32_BIT stat_len = SMC_inl(DATA_REG); status = stat_len & 0xffff; packet_length = stat_len >> 16;#else/* SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG ); packet_length = SMC_inw( DATA_REG );*/ // (Qinwei temp use, can remove. 03.01.08) //test rcv memory./* t1=ntohs(SMC_inw( DATA_REG )); t2=ntohs(SMC_inw( DATA_REG )); t3=ntohs(SMC_inw( DATA_REG )); t4=ntohs(SMC_inw( DATA_REG )); t5=ntohs(SMC_inw( DATA_REG )); t6=ntohs(SMC_inw( DATA_REG )); t7=ntohs(SMC_inw( DATA_REG )); t8=SMC_inw( DATA_REG ); t9=SMC_inw( DATA_REG ); t10=SMC_inw( DATA_REG ); t11=SMC_inw( DATA_REG ); */// status = SMC_inw( DATA_REG ); /* Qinwei: it seemed couldn't get the status from MEMORY, so BUG?*/ /* so temp mark it, ask Smsc for it. 2003.01.08 added by xu.*/ status = 0; //because bug. packet_length = SMC_inw( DATA_REG ); //take 2nd word from memory.#endif packet_length &= 0x07ff; /* mask off top bits and get the number of the bytes*/// PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ); if ( !(status & RS_ERRORS ) ){ /* Adjust for having already read the first two words */ packet_length -= 4; //4; //total bytes number -4. temp3 = packet_length; //add by xu. // set odd length for bug in LAN91C113, // which never sets RS_ODDFRAME /* TODO ? */#ifdef USE_32_BIT// PRINTK3(" Reading %d dwords (and %d bytes) \n", packet_length >> 2, packet_length & 3 ); /* QUESTION: Like in the TX routine, do I want to send the DWORDs or the bytes first, or some mixture. A mixture might improve already slow PIO performance */ SMC_insl( DATA_REG , NetRxPackets[0], packet_length >> 2 ); /* read the left over bytes */ if (packet_length & 3) { int i; byte *tail = NetRxPackets[0] + (packet_length & ~3); dword leftover = SMC_inl(DATA_REG); for (i=0; i<(packet_length & 3); i++) *tail++ = (byte) (leftover >> (8*i)) & 0xff; } #else// PRINTK3(" Reading %d words and %d byte(s) \n",// (packet_length >> 1 ), packet_length & 1 );//SMC_insw(DATA_REG , NetRxPackets[0], packet_length >> 1); //read as word,read all data.// SMC_insw(DATA_REG, datapt0, packet_length >>1);// temp4=packet_length; k=0; for(temp4=packet_length>>1;temp4>0;temp4--) //read data. { NetRxPackets[k] = SMC_inw( DATA_REG ); udelay(5); k++; } // /* Qinwei comments: no need to think for the odd byte, program will copy odd byte(if have) and control byte to the buffer*/#endif // USE_32_BIT /* t1=ntohs(NetRxPackets[0]); t2=ntohs(NetRxPackets[1]); t3=ntohs(NetRxPackets[2]); t4=ntohs(NetRxPackets[3]); t5=ntohs(NetRxPackets[4]); t6=ntohs(NetRxPackets[5]); t7=ntohs(NetRxPackets[6]); t8=ntohs(NetRxPackets[7]); t9=ntohs(NetRxPackets[8]); t10=ntohs(NetRxPackets[9]); t11=ntohs(NetRxPackets[10]); t12=ntohs(NetRxPackets[11]); t13=ntohs(NetRxPackets[12]); t14=ntohs(NetRxPackets[13]); t15=ntohs(NetRxPackets[14]); t16=ntohs(NetRxPackets[15]); t17=ntohs(NetRxPackets[16]); t18=ntohs(NetRxPackets[17]); t19=ntohs(NetRxPackets[18]); t20=ntohs(NetRxPackets[19]); t21=ntohs(NetRxPackets[20]); t22=ntohs(NetRxPackets[21]); t23=ntohs(NetRxPackets[22]); t24=ntohs(NetRxPackets[23]); t25=ntohs(NetRxPackets[24]); t26=ntohs(NetRxPackets[25]); t27=ntohs(NetRxPackets[26]); t28=ntohs(NetRxPackets[27]); t29=ntohs(NetRxPackets[28]); t30=ntohs(NetRxPackets[29]); t31=ntohs(NetRxPackets[30]); */ udelay(10); #if SMC_DEBUG > 2// printf("Receiving Packet\n");// print_packet( NetRxPackets[0], packet_length ); //rx test. #endif } else { /* error ... */ /* TODO ? */ is_error = 1; } while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) udelay(1); // Wait until not busy /* error or good, tell the card to get rid of this packet */// SMC_outw( MC_RELEASE, MMU_CMD_REG ); //del by xu SMC_outw( MC_REMOVE, MMU_CMD_REG ); //aad by xu while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) //wait for release complete. udelay(1); // Wait until not busy SMC_outw( MC_FREEPKT, MMU_CMD_REG ); if (!is_error) { /* Pass the packet up to the protocol layers. */ //convert word to bytes. //unsigned char ReceivePackets[MAX_LENGTH]; for(i=0;i<temp3/2-1;i++) { temp2=NetRxPackets[i]; ReceivePackets[2*i] = temp2; ReceivePackets[2*i+1] = temp2>>8; } if(NetRxPackets[temp3/2]&0x2000) //odd number. { packet_length=temp3-1; //del the control byte. ReceivePackets[temp3-2] = NetRxPackets[temp3/2-1]; // } else{packet_length=temp3-2; //enven bytes , del the last 2 bytes. } t23=NetRxPackets[0]; t24=NetRxPackets[1]; t25=NetRxPackets[2]; t26=NetRxPackets[3]; t27=NetRxPackets[4]; pointer = (byte *)NetRxPackets; /* t1=ReceivePackets[0]; t2=ReceivePackets[1]; t3=ReceivePackets[2]; t4=ReceivePackets[3]; t5=ReceivePackets[4]; t6=ReceivePackets[5]; t7=ReceivePackets[6]; t8=ReceivePackets[7]; t8=ReceivePackets[8]; */ t1=*pointer; t2=*(pointer+1); t3=*(pointer+2); t4=*(pointer+3); t5=*(pointer+4); temp1=ntohs(NetRxPackets[6]); //check is pro or frame length. if(temp1>1500) { NetReceive1(pointer, packet_length); //this packet_length is bytes number. return packet_length; } else if(temp1<=1500); { NetReceive2(ReceivePackets,packet_length); }// NetReceive(NetRxPackets[0], packet_length); //NetRecive() programed by xu. return packet_length; //packet_length used to copy the data to upper layer. } else { return 0; //Reiceive error. }}/*---------------------------------------------------- . smc_close . . this makes the board clean up everything that it can . and not talk to the outside world. Caused by . an 'ifconfig ethX down' . -----------------------------------------------------*/static int smc_close(){// PRINTK2("%s:smc_close\n", SMC_DEV_NAME); /* clear everything */ smc_shutdown(); return 0;}#if 0/*------------------------------------------------------------ . Modify a bit in the LAN91C111 register set .-------------------------------------------------------------*/static word smc_modify_regbit(int bank, int ioaddr, int reg, unsigned int bit, int val){ word regval; SMC_SELECT_BANK( bank ); regval = SMC_inw( reg ); if (val) regval |= bit; else regval &= ~bit; SMC_outw( regval, 0 ); return(regval);}/*------------------------------------------------------------ . Retrieve a bit in the LAN91C113 register set .-------------------------------------------------------------*/static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit){ SMC_SELECT_BANK( bank ); if ( SMC_inw( reg ) & bit) return(1); else return(0);}/*------------------------------------------------------------ . Modify a LAN91C113 register (word access only) .-------------------------------------------------------------*/static void smc_modify_reg(int bank, int ioaddr, int reg, word val){ SMC_SELECT_BANK( bank ); SMC_outw( val, reg );}/*------------------------------------------------------------ . Retrieve a LAN91C113 register (word access only) .-------------------------------------------------------------*/static int smc_get_reg(int bank, int ioaddr, int reg){ SMC_SELECT_BANK( bank ); return(SMC_inw( reg ));}#endif /* 0 *///---PHY CONTROL AND CONFIGURATION-----------------------------------------#if (SMC_DEBUG > 2 )/*------------------------------------------------------------ . Debugging function for viewing MII Management serial bitstream .-------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -