?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

/*! \file cs8900.c \brief Crystal CS8900 Ethernet Interface Driver. */
//*****************************************************************************
//
// File Name    : 'cs8900.c'
// Title                : Crystal CS8900 Ethernet Interface Driver
// Author               : Pascal Stang
// Created              : 11/7/2004
// Revised              : 11/7/2004
// Version              : 0.1
// Target MCU   : Atmel AVR series
// Editor Tabs  : 4
//
//*****************************************************************************

#include "global.h"
#include "timer.h"
#include "rprintf.h"

#include "cs8900.h"

// include configuration
#include "cs8900conf.h"

void nicInit(void)
{
        cs8900Init();
}

void nicSend(unsigned int len, unsigned char* packet)
{
        u08 timeout = 15;

        // request space in CS8900's on-chip memory for storing an outgoing frame
        cs8900Write16(CS8900_IO_TXCMD, TX_START_ALL_BYTES);
        cs8900Write16(CS8900_IO_TXLENGTH, len);
        // check if CS8900 is ready to accept the frame we want to send
        // (timeout after 1.5ms since it should only take 1.25ms to
        //  finish sending previous frame.  If we timeout, it's probably
        //  because there's no link, no ethernet cable.)
        while(!(cs8900ReadReg(PP_BusST) & READY_FOR_TX_NOW) && timeout)
        {
                // wait 100us
                delay_us(100);
                timeout--;
        }
        // write packet data bytes
        cs8900CopyToFrame(packet, len);

        // packet is automatically sent upon completion of above write
}

unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
{
        unsigned int packetLength;

        packetLength = cs8900BeginPacketRetreive();

        // if there's no packet or an error - exit without ending the operation
        if( !packetLength )
                return 0;

        // drop anything too big for the buffer
        if( packetLength > maxlen )
        {
                cs8900EndPacketRetreive();
                return 0;
        }
        
        // copy the packet data into the packet buffer
        cs8900RetreivePacketData( packet, packetLength );
        cs8900EndPacketRetreive();
                
        return packetLength;
}

void nicGetMacAddress(u08* macaddr)
{
        // read MAC address registers
        // TODO: check byte order here!
        *((unsigned short*)(macaddr+0)) = cs8900ReadReg(PP_IA+0);
        *((unsigned short*)(macaddr+2)) = cs8900ReadReg(PP_IA+2);
        *((unsigned short*)(macaddr+4)) = cs8900ReadReg(PP_IA+4);
}

void nicSetMacAddress(u08* macaddr)
{
        // write MAC address registers
        cs8900WriteReg(PP_IA+0, (macaddr[1]<<8) + macaddr[0] );
        cs8900WriteReg(PP_IA+2, (macaddr[3]<<8) + macaddr[2] );
        cs8900WriteReg(PP_IA+4, (macaddr[5]<<8) + macaddr[4] );
}

unsigned int cs8900BeginPacketRetreive(void)
{
        unsigned short status;

        // check RxEvent
        status = cs8900ReadReg(PP_RxEvent);

        if( !((status&RX_OK)||(status&RX_IA)||(status&RX_BROADCAST)) )
        {
                return 0;
        }

//      return cs8900ReadReg(PP_RxFrameByteCnt);
        // read RxStatus high-byte first
        status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
        status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);
        // read packet length high-byte first
        status =  cs8900Read(CS8900_IO_RXTX_DATA_PORT0+1)<<8;
        status |= cs8900Read(CS8900_IO_RXTX_DATA_PORT0+0);

        return status;
}

void cs8900RetreivePacketData(u08* packet, unsigned int packetLength )
{
        cs8900CopyFromFrame(packet, packetLength);
}

void cs8900EndPacketRetreive(void)
{
        // dummy read first four bytes
        //cs8900CopyFromFrame(packet, 4);
}



void cs8900InitPorts(void)
{
#if MEMORY_MAPPED_NIC == 1
        // enable external SRAM interface - no wait states
        sbi(MCUSR, SRE);
#else
        // set address port to output
        outb(CS8900_ADDRESS_DDR, CS8900_ADDRESS_MASK);
    
        // set data port to input with pull-ups
        outb(CS8900_DATA_DDR, 0x00);
        outb(CS8900_DATA_PORT, 0xFF);

        // initialize the control port read and write pins to de-asserted
        sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN );
        sbi( CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN );
        // set the read and write pins to output
        sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_READPIN );
        sbi( CS8900_CONTROL_DDR, CS8900_CONTROL_WRITEPIN );
#endif
        // set reset pin to output
        sbi( CS8900_RESET_DDR, CS8900_RESET_PIN );
}

void cs8900Init(void)
{
        cs8900InitPorts();

        // assert hardware reset
        sbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
        // wait
        delay_ms(10);
        // release hardware reset
        cbi( CS8900_RESET_PORT, CS8900_RESET_PIN );
        delay_ms(10);
        
        // Reset the Ethernet-Controller
        cs8900Write16(CS8900_IO_PP_PTR, PP_SelfCTL);
        cs8900Write16(CS8900_IO_PP_DATA_PORT0, POWER_ON_RESET);
        // wait until chip-reset is done
        cs8900Write16(CS8900_IO_PP_PTR, PP_SelfST);
        while(!(cs8900Read16(CS8900_IO_PP_DATA_PORT0) & INIT_DONE));

        // set our MAC as Individual Address
        cs8900WriteReg(PP_IA+0, (CS8900_MAC1<<8) + CS8900_MAC0 );
        cs8900WriteReg(PP_IA+2, (CS8900_MAC3<<8) + CS8900_MAC2 );
        cs8900WriteReg(PP_IA+4, (CS8900_MAC5<<8) + CS8900_MAC4 );
        // configure the Physical Interface
        cs8900WriteReg(PP_LineCTL, SERIAL_RX_ON | SERIAL_TX_ON);
        cs8900WriteReg(PP_RxCTL, RX_OK_ACCEPT | RX_IA_ACCEPT | RX_BROADCAST_ACCEPT );
}

void cs8900Write(unsigned char address, unsigned char data)
{
        // assert the address
        outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
        // set data bus as output
        outb(CS8900_DATA_DDR, 0xFF);
        // place data on bus
        outb(CS8900_DATA_PORT, data);
        // clock write pin
        cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
        nop();
        nop();
        nop();
        nop();
        sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_WRITEPIN);
        // set data bus back to input with pullups enabled
        outb(CS8900_DATA_DDR, 0x00);
        outb(CS8900_DATA_PORT, 0xFF);
}

unsigned char cs8900Read(unsigned char address)
{
        unsigned char data;
        // assert the address
        outb(CS8900_ADDRESS_PORT, address | (inb(CS8900_ADDRESS_PORT)&~CS8900_ADDRESS_MASK));
        // set data bus to input with pullups enabled
        outb(CS8900_DATA_DDR, 0x00);
        outb(CS8900_DATA_PORT, 0xFF);
        // assert read
        cbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
        nop();
        nop();
        nop();
        nop();
        // read in the data
        data = inb( CS8900_DATA_PIN );
        // negate read
        sbi(CS8900_CONTROL_PORT, CS8900_CONTROL_READPIN);
        // return data
        return data;
}

void cs8900Write16(unsigned char address, unsigned short data)
{
        cs8900Write(address+0, data);   
        cs8900Write(address+1, data>>8);        
}

unsigned short cs8900Read16(unsigned char address)
{
        unsigned short data;
        data =  cs8900Read(address+0);
        data |= cs8900Read(address+1)<<8;
        return data;
}

// writes a word in little-endian byte order to a specified PacketPage address
void cs8900WriteReg(unsigned short address, unsigned short data)
{
        cs8900Write16(CS8900_IO_PP_PTR, address);
        cs8900Write16(CS8900_IO_PP_DATA_PORT0, data);
}

// reads a word in little-endian byte order from a specified PacketPage address
unsigned short cs8900ReadReg(unsigned short address)
{
        cs8900Write16(CS8900_IO_PP_PTR, address);
        return cs8900Read16(CS8900_IO_PP_DATA_PORT0);
}

// copies bytes from MCU-memory to frame port
// NOTES: * an odd number of byte may only be transfered
//          if the frame is written to the end!
//        * MCU-memory MUST start at word-boundary

void cs8900CopyToFrame(unsigned char *source, unsigned short size)
{
        while(size>1)
        {
                cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *((unsigned short*)source));
                source += 2;
                size -= 2;
        }
        // if odd num. of bytes...
        // write leftover byte (the LAN-controller ignores the highbyte)
        if(size)
                cs8900Write16(CS8900_IO_RXTX_DATA_PORT0, *(unsigned char*)source);
}

// copies bytes from frame port to MCU-memory
// NOTES: * an odd number of byte may only be transfered
//          if the frame is read to the end!
//        * MCU-memory MUST start at word-boundary

void cs8900CopyFromFrame(unsigned char *dest, unsigned short size)
{
        while(size>1)
        {
                *((unsigned short *)dest) = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
                dest += 2;
                size -= 2;
        }
  
        // check for leftover byte...
        // the LAN-Controller will return 0 for the highbyte
        if(size)        
                *(unsigned char *)dest = cs8900Read16(CS8900_IO_RXTX_DATA_PORT0);
}

void cs8900IORegDump(void)
{
        rprintfProgStrM("CS8900 I/O Registers\r\n");
        rprintfProgStrM(" FRAME   ISQ  ADDR DATA0 DATA1\r\n");
        rprintfProgStrM("-------------------------------\r\n");
        rprintfProgStrM("  ");
        rprintfu16(cs8900Read16(CS8900_IO_RXTX_DATA_PORT0));
        rprintfProgStrM("  ");
        rprintfu16(cs8900Read16(CS8900_IO_ISQ));
        rprintfProgStrM("  ");
        rprintfu16(cs8900Read16(CS8900_IO_PP_PTR));
        rprintfProgStrM("  ");
        rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT0));
        rprintfProgStrM("  ");
        rprintfu16(cs8900Read16(CS8900_IO_PP_DATA_PORT1));
        rprintfCRLF();
}

void cs8900RegDump(void)
{
        rprintfProgStrM("CS8900 PacketPage Registers\r\n");
        rprintfProgStrM("CHIP ID: ");
        rprintfu16(cs8900ReadReg(PP_ChipID));
        rprintfCRLF();

        rprintfProgStrM("PP_ISAIOB: ");
        rprintfu16(cs8900ReadReg(PP_ISAIOB));
        rprintfCRLF();

        rprintfProgStrM("MAC addr: ");
        rprintfu16(cs8900ReadReg(PP_IA+0));
        rprintfu16(cs8900ReadReg(PP_IA+2));
        rprintfu16(cs8900ReadReg(PP_IA+4));
        rprintfCRLF();
}

void nicRegDump(void)
{
        cs8900IORegDump();
        cs8900RegDump();
}


u08 cs8900LinkStatus(void)
{
        if(cs8900ReadReg(PP_LineST) & LINK_OK)
                return 1;
        else
                return 0;
}
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3