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

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 unsigned int cs8900BeginPacketRetreive(void)
00086 {
00087     unsigned short status;
00088 
00089     // check RxEvent
00090     status = cs8900ReadReg(PP_RxEvent);
00091 
00092     if( !((status&RX_OK)||(status&RX_IA)||(status&RX_BROADCAST)) )
00093     {
00094         return 0;
00095     }
00096 
00097 //  return cs8900ReadReg(PP_RxFrameByteCnt);
00098     // read RxStatus high-byte first
00099     status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
00100     status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);
00101     // read packet length high-byte first
00102     status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
00103     status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);
00104 
00105     return status;
00106 }
00107 
00108 void cs8900RetreivePacketData(u08* packet, unsigned int packetLength )
00109 {
00110     cs8900CopyFromFrame(packet, packetLength);
00111 }
00112 
00113 void cs8900EndPacketRetreive(void)
00114 {
00115     // dummy read first four bytes
00116     //cs8900CopyFromFrame(packet, 4);
00117 }
00118 
00119 
00120 
00121 void cs8900InitPorts(void)
00122 {
00123 #if MEMORY_MAPPED_NIC == 1
00124     // enable external SRAM interface - no wait states
00125     sbi(MCUSR, SRE);
00126 #else
00127     // set address port to output
00128     outb(CS8900_ADDRESS_DDR, CS8900_ADDRESS_MASK);
00129     
00130     // set data port to input with pull-ups
00131     outb(CS8900_DATA_DDR, 0x00);
00132     outb(CS8900_DATA_PORT, 0xFF);
00133 
00134     // initialize the control port read and write pins to de-asserted
00135     sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN );
00136     sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN );
00137     // set the read and write pins to output
00138     sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_READPIN );
00139     sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_WRITEPIN );
00140 #endif
00141     // set reset pin to output
00142     sbi( CS8900_RESET_DDR, CS8900_RESET_PIN );
00143 }
00144 
00145 void cs8900Init(void)
00146 {
00147     cs8900InitPorts();
00148 
00149     // assert hardware reset
00150     sbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
00151     // wait
00152     delay_ms(10);
00153     // release hardware reset
00154     cbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
00155     delay_ms(10);
00156     
00157     // Reset the Ethernet-Controller
00158     cs8900Write16(CS8900_IO_PP_PTR, PP_SelfCTL);
00159     cs8900Write16(CS8900_IO_PP_DATA_PORT0, POWER_ON_RESET);
00160     // wait until chip-reset is done
00161     cs8900Write16(CS8900_IO_PP_PTR, PP_SelfST);
00162     while(!(cs8900Read16(CS8900_IO_PP_DATA_PORT0) & INIT_DONE));
00163 
00164     // set our MAC as Individual Address
00165     cs8900WriteReg(PP_IA+0, (CS8900_MAC1<<8) + CS8900_MAC0 );
00166     cs8900WriteReg(PP_IA+2, (CS8900_MAC3<<8) + CS8900_MAC2 );
00167     cs8900WriteReg(PP_IA+4, (CS8900_MAC5<<8) + CS8900_MAC4 );
00168     // configure the Physical Interface
00169     cs8900WriteReg(PP_LineCTL, SERIAL_RX_ON | SERIAL_TX_ON);
00170     cs8900WriteReg(PP_RxCTL, RX_OK_ACCEPT | RX_IA_ACCEPT | RX_BROADCAST_ACCEPT );
00171 }
00172 
00173 void cs8900Write(unsigned char address, unsigned char data)
00174 {
00175     // assert the address
00176     outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
00177     // set data bus as output
00178     outb(CS8900_DATA_DDR, 0xFF);
00179     // place data on bus
00180     outb(CS8900_DATA_PORT, data);
00181     // clock write pin
00182     cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
00183     nop();
00184     nop();
00185     nop();
00186     nop();
00187     sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
00188     // set data bus back to input with pullups enabled
00189     outb(CS8900_DATA_DDR, 0x00);
00190     outb(CS8900_DATA_PORT, 0xFF);
00191 }
00192 
00193 unsigned char cs8900Read(unsigned char address)
00194 {
00195     unsigned char data;
00196     // assert the address
00197     outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
00198     // set data bus to input with pullups enabled
00199     outb(CS8900_DATA_DDR, 0x00);
00200     outb(CS8900_DATA_PORT, 0xFF);
00201     // assert read
00202     cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
00203     nop();
00204     nop();
00205     nop();
00206     nop();
00207     // read in the data
00208     data = inb( CS8900_DATA_PIN );
00209     // negate read
00210     sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
00211     // return data
00212     return data;
00213 }
00214 
00215 void cs8900Write16(unsigned char address, unsigned short data)
00216 {
00217     cs8900Write(address+0, data);   
00218     cs8900Write(address+1, data>>8);    
00219 }
00220 
00221 unsigned short cs8900Read16(unsigned char address)
00222 {
00223     unsigned short data;
00224     data =  cs8900Read(address+0);
00225     data |= cs8900Read(address+1)<<8;
00226     return data;
00227 }
00228 
00229 // writes a word in little-endian byte order to a specified PacketPage address
00230 void cs8900WriteReg(unsigned short address, unsigned short data)
00231 {
00232     cs8900Write16(CS8900_IO_PP_PTR, address);
00233     cs8900Write16(CS8900_IO_PP_DATA_PORT0, data);
00234 }
00235 
00236 // reads a word in little-endian byte order from a specified PacketPage address
00237 unsigned short cs8900ReadReg(unsigned short address)
00238 {
00239     cs8900Write16(CS8900_IO_PP_PTR, address);
00240     return cs8900Read16(CS8900_IO_PP_DATA_PORT0);
00241 }
00242 
00243 // copies bytes from MCU-memory to frame port
00244 // NOTES: * an odd number of byte may only be transfered
00245 //          if the frame is written to the end!
00246 //        * MCU-memory MUST start at word-boundary
00247 
00248 void cs8900CopyToFrame(unsigned char *source, unsigned short size)
00249 {
00250     while(size>1)
00251     {
00252         cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *((unsigned short*)source));
00253         source += 2;
00254         size -= 2;
00255     }
00256     // if odd num. of bytes...
00257     // write leftover byte (the LAN-controller ignores the highbyte)
00258     if(size)
00259         cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *(unsigned char*)source);
00260 }
00261 
00262 // copies bytes from frame port to MCU-memory
00263 // NOTES: * an odd number of byte may only be transfered
00264 //          if the frame is read to the end!
00265 //        * MCU-memory MUST start at word-boundary
00266 
00267 void cs8900CopyFromFrame(unsigned char *dest, unsigned short size)
00268 {
00269     while(size>1)
00270     {
00271         *((unsigned short *)dest) = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
00272         dest += 2;
00273         size -= 2;
00274     }
00275   
00276     // check for leftover byte...
00277     // the LAN-Controller will return 0 for the highbyte
00278     if(size)    
00279         *(unsigned char *)dest = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
00280 }
00281 
00282 void cs8900IORegDump(void)
00283 {
00284     rprintfProgStrM("CS8900 I/O Registers\r\n");
00285     rprintfProgStrM(" FRAME   ISQ  ADDR DATA0 DATA1\r\n");
00286     rprintfProgStrM("-------------------------------\r\n");
00287     rprintfProgStrM("  ");
00288     rprintfu16(cs8900Read16(CS8900_IO_RXTX_DATA_PORT0));
00289     rprintfProgStrM("  ");
00290     rprintfu16(cs8900Read16(CS8900_IO_ISQ));
00291     rprintfProgStrM("  ");
00292     rprintfu16(cs8900Read16(CS8900_IO_PP_PTR));
00293     rprintfProgStrM("  ");
00294     rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT0));
00295     rprintfProgStrM("  ");
00296     rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT1));
00297     rprintfCRLF();
00298 }
00299 
00300 void cs8900RegDump(void)
00301 {
00302     rprintfProgStrM("CS8900 PacketPage Registers\r\n");
00303     rprintfProgStrM("CHIP ID: ");
00304     rprintfu16(cs8900ReadReg(PP_ChipID));
00305     rprintfCRLF();
00306 
00307     rprintfProgStrM("PP_ISAIOB: ");
00308     rprintfu16(cs8900ReadReg(PP_ISAIOB));
00309     rprintfCRLF();
00310 
00311     rprintfProgStrM("MAC addr: ");
00312     rprintfu16(cs8900ReadReg(PP_IA+0));
00313     rprintfu16(cs8900ReadReg(PP_IA+2));
00314     rprintfu16(cs8900ReadReg(PP_IA+4));
00315     rprintfCRLF();
00316 }
00317 
00318 void nicRegDump(void)
00319 {
00320     cs8900IORegDump();
00321     cs8900RegDump();
00322 }
00323 
00324 
00325 u08 cs8900LinkStatus(void)
00326 {
00327     if(cs8900ReadReg(PP_LineST) & LINK_OK)
00328         return 1;
00329     else
00330         return 0;
00331 }

Generated on Mon Aug 22 04:29:27 2005 for Procyon AVRlib by  doxygen 1.4.2