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 }