Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

cs8900.c

Go to the documentation of this file.
00001 /*! \file cs8900.c \brief Crystal CS8900 Ethernet Interface Driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'cs8900.c'
00005 // Title        : Crystal CS8900 Ethernet Interface Driver
00006 // Author       : Pascal Stang
00007 // Created      : 11/7/2004
00008 // Revised      : 11/7/2004
00009 // Version      : 0.1
00010 // Target MCU   : Atmel AVR series
00011 // Editor Tabs  : 4
00012 //
00013 //*****************************************************************************
00014 
00015 #include "global.h"
00016 #include "timer.h"
00017 #include "rprintf.h"
00018 
00019 #include "cs8900.h"
00020 
00021 // include configuration
00022 #include "cs8900conf.h"
00023 
00024 void nicInit(void)
00025 {
00026     cs8900Init();
00027 }
00028 
00029 void nicSend(unsigned int len, unsigned char* packet)
00030 {
00031     u08 timeout = 15;
00032 
00033     // request space in CS8900's on-chip memory for storing an outgoing frame
00034     cs8900Write16(CS8900_IO_TXCMD, TX_START_ALL_BYTES);
00035     cs8900Write16(CS8900_IO_TXLENGTH, len);
00036     // check if CS8900 is ready to accept the frame we want to send
00037     // (timeout after 1.5ms since it should only take 1.25ms to
00038     //  finish sending previous frame.  If we timeout, it's probably
00039     //  because there's no link, no ethernet cable.)
00040     while(!(cs8900ReadReg(PP_BusST) & READY_FOR_TX_NOW) && timeout)
00041     {
00042         // wait 100us
00043         delay_us(100);
00044         timeout--;
00045     }
00046     // write packet data bytes
00047     cs8900CopyToFrame(packet, len);
00048 
00049     // packet is automatically sent upon completion of above write
00050 }
00051 
00052 unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
00053 {
00054     unsigned int packetLength;
00055 
00056     packetLength = cs8900BeginPacketRetreive();
00057 
00058     // if there's no packet or an error - exit without ending the operation
00059     if( !packetLength )
00060         return 0;
00061 
00062     // drop anything too big for the buffer
00063     if( packetLength > maxlen )
00064     {
00065         cs8900EndPacketRetreive();
00066         return 0;
00067     }
00068     
00069     // copy the packet data into the packet buffer
00070     cs8900RetreivePacketData( packet, packetLength );
00071     cs8900EndPacketRetreive();
00072         
00073     return packetLength;
00074 }
00075 
00076 void nicGetMacAddress(u08* macaddr)
00077 {
00078     // read MAC address registers
00079     // TODO: check byte order here!
00080     *((unsigned short*)(macaddr+0)) = cs8900ReadReg(PP_IA+0);
00081     *((unsigned short*)(macaddr+2)) = cs8900ReadReg(PP_IA+2);
00082     *((unsigned short*)(macaddr+4)) = cs8900ReadReg(PP_IA+4);
00083 }
00084 
00085 void nicSetMacAddress(u08* macaddr)
00086 {
00087     // write MAC address registers
00088     cs8900WriteReg(PP_IA+0, (macaddr[1]<<8) + macaddr[0] );
00089     cs8900WriteReg(PP_IA+2, (macaddr[3]<<8) + macaddr[2] );
00090     cs8900WriteReg(PP_IA+4, (macaddr[5]<<8) + macaddr[4] );
00091 }
00092 
00093 unsigned int cs8900BeginPacketRetreive(void)
00094 {
00095     unsigned short status;
00096 
00097     // check RxEvent
00098     status = cs8900ReadReg(PP_RxEvent);
00099 
00100     if( !((status&RX_OK)||(status&RX_IA)||(status&RX_BROADCAST)) )
00101     {
00102         return 0;
00103     }
00104 
00105 //  return cs8900ReadReg(PP_RxFrameByteCnt);
00106     // read RxStatus high-byte first
00107     status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
00108     status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);
00109     // read packet length high-byte first
00110     status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
00111     status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);
00112 
00113     return status;
00114 }
00115 
00116 void cs8900RetreivePacketData(u08* packet, unsigned int packetLength )
00117 {
00118     cs8900CopyFromFrame(packet, packetLength);
00119 }
00120 
00121 void cs8900EndPacketRetreive(void)
00122 {
00123     // dummy read first four bytes
00124     //cs8900CopyFromFrame(packet, 4);
00125 }
00126 
00127 
00128 
00129 void cs8900InitPorts(void)
00130 {
00131 #if MEMORY_MAPPED_NIC == 1
00132     // enable external SRAM interface - no wait states
00133     sbi(MCUSR, SRE);
00134 #else
00135     // set address port to output
00136     outb(CS8900_ADDRESS_DDR, CS8900_ADDRESS_MASK);
00137     
00138     // set data port to input with pull-ups
00139     outb(CS8900_DATA_DDR, 0x00);
00140     outb(CS8900_DATA_PORT, 0xFF);
00141 
00142     // initialize the control port read and write pins to de-asserted
00143     sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN );
00144     sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN );
00145     // set the read and write pins to output
00146     sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_READPIN );
00147     sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_WRITEPIN );
00148 #endif
00149     // set reset pin to output
00150     sbi( CS8900_RESET_DDR, CS8900_RESET_PIN );
00151 }
00152 
00153 void cs8900Init(void)
00154 {
00155     cs8900InitPorts();
00156 
00157     // assert hardware reset
00158     sbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
00159     // wait
00160     delay_ms(10);
00161     // release hardware reset
00162     cbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
00163     delay_ms(10);
00164     
00165     // Reset the Ethernet-Controller
00166     cs8900Write16(CS8900_IO_PP_PTR, PP_SelfCTL);
00167     cs8900Write16(CS8900_IO_PP_DATA_PORT0, POWER_ON_RESET);
00168     // wait until chip-reset is done
00169     cs8900Write16(CS8900_IO_PP_PTR, PP_SelfST);
00170     while(!(cs8900Read16(CS8900_IO_PP_DATA_PORT0) & INIT_DONE));
00171 
00172     // set our MAC as Individual Address
00173     cs8900WriteReg(PP_IA+0, (CS8900_MAC1<<8) + CS8900_MAC0 );
00174     cs8900WriteReg(PP_IA+2, (CS8900_MAC3<<8) + CS8900_MAC2 );
00175     cs8900WriteReg(PP_IA+4, (CS8900_MAC5<<8) + CS8900_MAC4 );
00176     // configure the Physical Interface
00177     cs8900WriteReg(PP_LineCTL, SERIAL_RX_ON | SERIAL_TX_ON);
00178     cs8900WriteReg(PP_RxCTL, RX_OK_ACCEPT | RX_IA_ACCEPT | RX_BROADCAST_ACCEPT );
00179 }
00180 
00181 void cs8900Write(unsigned char address, unsigned char data)
00182 {
00183     // assert the address
00184     outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
00185     // set data bus as output
00186     outb(CS8900_DATA_DDR, 0xFF);
00187     // place data on bus
00188     outb(CS8900_DATA_PORT, data);
00189     // clock write pin
00190     cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
00191     nop();
00192     nop();
00193     nop();
00194     nop();
00195     sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
00196     // set data bus back to input with pullups enabled
00197     outb(CS8900_DATA_DDR, 0x00);
00198     outb(CS8900_DATA_PORT, 0xFF);
00199 }
00200 
00201 unsigned char cs8900Read(unsigned char address)
00202 {
00203     unsigned char data;
00204     // assert the address
00205     outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
00206     // set data bus to input with pullups enabled
00207     outb(CS8900_DATA_DDR, 0x00);
00208     outb(CS8900_DATA_PORT, 0xFF);
00209     // assert read
00210     cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
00211     nop();
00212     nop();
00213     nop();
00214     nop();
00215     // read in the data
00216     data = inb( CS8900_DATA_PIN );
00217     // negate read
00218     sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
00219     // return data
00220     return data;
00221 }
00222 
00223 void cs8900Write16(unsigned char address, unsigned short data)
00224 {
00225     cs8900Write(address+0, data);   
00226     cs8900Write(address+1, data>>8);    
00227 }
00228 
00229 unsigned short cs8900Read16(unsigned char address)
00230 {
00231     unsigned short data;
00232     data =  cs8900Read(address+0);
00233     data |= cs8900Read(address+1)<<8;
00234     return data;
00235 }
00236 
00237 // writes a word in little-endian byte order to a specified PacketPage address
00238 void cs8900WriteReg(unsigned short address, unsigned short data)
00239 {
00240     cs8900Write16(CS8900_IO_PP_PTR, address);
00241     cs8900Write16(CS8900_IO_PP_DATA_PORT0, data);
00242 }
00243 
00244 // reads a word in little-endian byte order from a specified PacketPage address
00245 unsigned short cs8900ReadReg(unsigned short address)
00246 {
00247     cs8900Write16(CS8900_IO_PP_PTR, address);
00248     return cs8900Read16(CS8900_IO_PP_DATA_PORT0);
00249 }
00250 
00251 // copies bytes from MCU-memory to frame port
00252 // NOTES: * an odd number of byte may only be transfered
00253 //          if the frame is written to the end!
00254 //        * MCU-memory MUST start at word-boundary
00255 
00256 void cs8900CopyToFrame(unsigned char *source, unsigned short size)
00257 {
00258     while(size>1)
00259     {
00260         cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *((unsigned short*)source));
00261         source += 2;
00262         size -= 2;
00263     }
00264     // if odd num. of bytes...
00265     // write leftover byte (the LAN-controller ignores the highbyte)
00266     if(size)
00267         cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *(unsigned char*)source);
00268 }
00269 
00270 // copies bytes from frame port to MCU-memory
00271 // NOTES: * an odd number of byte may only be transfered
00272 //          if the frame is read to the end!
00273 //        * MCU-memory MUST start at word-boundary
00274 
00275 void cs8900CopyFromFrame(unsigned char *dest, unsigned short size)
00276 {
00277     while(size>1)
00278     {
00279         *((unsigned short *)dest) = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
00280         dest += 2;
00281         size -= 2;
00282     }
00283   
00284     // check for leftover byte...
00285     // the LAN-Controller will return 0 for the highbyte
00286     if(size)    
00287         *(unsigned char *)dest = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
00288 }
00289 
00290 void cs8900IORegDump(void)
00291 {
00292     rprintfProgStrM("CS8900 I/O Registers\r\n");
00293     rprintfProgStrM(" FRAME   ISQ  ADDR DATA0 DATA1\r\n");
00294     rprintfProgStrM("-------------------------------\r\n");
00295     rprintfProgStrM("  ");
00296     rprintfu16(cs8900Read16(CS8900_IO_RXTX_DATA_PORT0));
00297     rprintfProgStrM("  ");
00298     rprintfu16(cs8900Read16(CS8900_IO_ISQ));
00299     rprintfProgStrM("  ");
00300     rprintfu16(cs8900Read16(CS8900_IO_PP_PTR));
00301     rprintfProgStrM("  ");
00302     rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT0));
00303     rprintfProgStrM("  ");
00304     rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT1));
00305     rprintfCRLF();
00306 }
00307 
00308 void cs8900RegDump(void)
00309 {
00310     rprintfProgStrM("CS8900 PacketPage Registers\r\n");
00311     rprintfProgStrM("CHIP ID: ");
00312     rprintfu16(cs8900ReadReg(PP_ChipID));
00313     rprintfCRLF();
00314 
00315     rprintfProgStrM("PP_ISAIOB: ");
00316     rprintfu16(cs8900ReadReg(PP_ISAIOB));
00317     rprintfCRLF();
00318 
00319     rprintfProgStrM("MAC addr: ");
00320     rprintfu16(cs8900ReadReg(PP_IA+0));
00321     rprintfu16(cs8900ReadReg(PP_IA+2));
00322     rprintfu16(cs8900ReadReg(PP_IA+4));
00323     rprintfCRLF();
00324 }
00325 
00326 void nicRegDump(void)
00327 {
00328     cs8900IORegDump();
00329     cs8900RegDump();
00330 }
00331 
00332 
00333 u08 cs8900LinkStatus(void)
00334 {
00335     if(cs8900ReadReg(PP_LineST) & LINK_OK)
00336         return 1;
00337     else
00338         return 0;
00339 }

Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by  doxygen 1.4.2