#if 0 source makefile.tcl return #endif #include "fei82559.h" #include "debug.h" #include "io.h" bool Fei82559::Hw::init() { ScbControlStatus cs; cs.all=0; cs.ack->all=~0; cs.interruptGlobalMask=1; scbControlStatus->all=cs.all; /* cs.interrupt->all=~0; scbControlStatus->all=cs.all; */ mdi->write(0,0,0x0400); mdi->write(1,0,0x2100); { static Ias ias[1] __attribute__ ((aligned (16))); ias->commandStatus->all=0; ias->commandStatus->el=1; ias->commandStatus->cmd=1; ias->link=0; for(U32 i=0;i<3;i++) { U32 word=0; eeprom->read(i,&word); ias->words[i]=word; } ifdebug(1) { for(U32 i=0;i<6;i++) { debug.sendHex(ias->bytes[i]); debug<<':'; } debug<<"\r\n"; } ias->words[3]=0; doCu(ias); } { struct ConfigInit: public Config { U32 buf[8]; }; static ConfigInit config[1] __attribute__ ((aligned (16))); config->commandStatus->all=0; config->commandStatus->el=1; config->commandStatus->cmd=2; config->link=0; config->buf[0]=0x00008816; config->buf[1]=0x03300000; config->buf[2]=0x002e0001; config->buf[3]=0x48f20060 | 0x01000000 /* promiscuous */; config->buf[4]=0x00f24000; config->buf[5]=0x00000d3f; doCu(config); } return true; } bool Fei82559::Hw::dump() { static Dump dump[1] __attribute__ ((aligned (16))); dump->commandStatus->all=0; dump->commandStatus->el=1; dump->commandStatus->cmd=6; dump->buf=(U32)dump->data; dump->link=0; doCu(dump); debug.dump((U8*)dump->data,sizeof(dump->data)); return true; } bool Fei82559::Hw::Mdi::access (U32 phyAdd,U32 regAdd,U32 *data,U32 opCode) { Control c; U32 dcnt=40; c.all=0; c.phyAdd=phyAdd; c.regAdd=regAdd; c.data=*data; c.opCode=opCode; control->all=c.all; while(dcnt) { c.all=control->all; if(c.ready) break; dcnt--; volatile U8 any; any=*(Io*)0x84; } *data=c.data; return true; } void Fei82559::Hw::Eeprom::bitDelay() { volatile U32 dcnt=10; while(dcnt) { volatile U8 any; any=*(Io*)0x84; dcnt--; } } bool Fei82559::Hw::Eeprom::cmd(U32 cmd,U32 address,U32 *data) { Control c; U32 dcnt,bit; U32 d; c.all=control->all; cmd|=(address<all=c.all; bitDelay(); c.ck=1; control->all=c.all; bitDelay(); if(control->dout) d|=(1<all=c.all; bitDelay(); if(data) { *data=d; } return true; } bool Fei82559::Hw::doCu(Cb *cb) { ScbControlStatus cs; ifdebug(2) { asm("invd"); debug<<"cu "<<(U32)cb<<" "<all<<"\r\n"; } while(1) { asm("invd"); cs.all=scbControlStatus->all; if(cs.cus==0) break; } scbControlStatus->all=cs.all; ifdebug(2) { asm("invd"); debug<<"cu "<<(U32)cb<<" "<all<<"\r\n"; for(int i=0;i<6;i++) debug<<((U32*)cb)[i]<<' '; debug<<"\r\n"; } asm("wbinvd"); scbGeneralPointer=(U32)cb; cs.cuc=1; scbControlStatus->all=cs.all; while(1) { asm("invd"); cs.all=scbControlStatus->all; if(cs.cuc==0) break; } while(1) { asm("invd"); if(cb->commandStatus->c) break; } cs.ack->all=~0; scbControlStatus->all=cs.all; asm("wbinvd"); ifdebug(2) { debug<<"cu " << (int)cb->commandStatus->ok <<"\r\n"; } return cb->commandStatus->ok; } bool Fei82559::Hw::doCuResume() { ScbControlStatus cs; ifdebug(2) { asm("invd"); debug<<"cu resume "<all<<"\r\n"; } while(1) { asm("invd"); cs.all=scbControlStatus->all; if(cs.cuc==0) break; } cs.cuc=2; scbControlStatus->all=cs.all; asm("wbinvd"); while(1) { asm("invd"); cs.all=scbControlStatus->all; if(cs.cuc==0) break; } return true; } bool Fei82559::Hw::doRu(Cb *cb) { ScbControlStatus cs; ifdebug(2) { asm("invd"); cs.all=scbControlStatus->all; debug<<"ru "<<(U32)cb<<" "<all; if(cs.ruc==0) break; } if(cs.rus==2) { cs.ruc=4; scbControlStatus->all=cs.all; while(1) { asm("invd"); cs.all=scbControlStatus->all; if(cs.ruc==0) break; } } scbControlStatus->all=cs.all; ifdebug(2) { for(int i=0;i<6;i++) debug<<((U32*)cb)[i]<<' '; debug<<"\r\n"; } asm("wbinvd"); scbGeneralPointer=(U32)cb; cs.ruc=1; scbControlStatus->all=cs.all; return true; } bool Fei82559::Hw::receiveTodo(Rd *rd,U32 len) { rd->commandStatus->all=0; rd->commandStatus->el=1; rd->link=(U32)rd; rd->reserved=0xffffffff; rd->sizes->all=0; rd->sizes->size=len; return doRu(rd); } bool Fei82559::Hw::receiveDone(Rd *rd,U32 *len) { ScbControlStatus cs; asm("invd"); cs.all=scbControlStatus->all; scbControlStatus->all=cs.all; if(!rd->commandStatus->c) return false; *len=rd->sizes->actual; ifdebug(4) { debug<<"ru " << (int)rd->commandStatus->ok <<"\r\n"; } return true; } Fei82559::Fei82559() { hw=0; debug<<"Fei82559::Fei82559 "<<((U32)this)<<"\r\n"; } /* Fei82559::~Fei82559() { } */ bool Fei82559::init() { Td *td; Rd *rd; debug<<"Fei82559::init\r\n"; hw->init(); currentTd=(Td*)(U8*)buf; currentRd=(Rd*)(currentTd+tdsCount); td=currentTd; for(unsigned i=0;icommandStatus->all=0; td->commandStatus->s=1; td->commandStatus->c=1; td->tbds=(Hw::Tbd*)~0U; td->link=(U32)(td+1); td=(Td*)(U32)td->link; } td[-1].link=(U32)currentTd; rd=currentRd; for(unsigned i=0;icommandStatus->all=0; //rd->commandStatus->el=1; rd->reserved=0xffffffff; rd->sizes->all=0; rd->sizes->size=Ethernet::MTU; rd->link=(U32)(rd+1); rd=(Rd*)(U32)rd->link; } rd[-1].link=(U32)currentRd; // a nop for start cu currentTd->commandStatus->all=0; currentTd->commandStatus->s=1; currentTd->commandStatus->cmd=0; hw->doCu(currentTd); hw->doRu(currentRd); return true; } void Fei82559::reset() { } Ethernet *Fei82559::receive(U32 *size) { Rd* rd; rd=currentRd; asm("invd"); if(!rd->commandStatus->c) { ifdebug(1) { debug<<"Fei82559 receive\r\n"; } if(hw->scbControlStatus->rus!=4) { ifdebug(1) { debug<<"Fei82559 restart\r\n"; } hw->doRu(currentRd); } return 0; } *size=rd->sizes->actual; currentRd=(Rd*)(U32)rd->link; //hw->doRu(currentRd); ifdebug(8) { debug<<"Fei82559 receive "<< (U32)rd->ethernet << ' ' << *size << "\r\n"; } return rd->ethernet; } void Fei82559::receive(Ethernet *e) { Rd* rd=0; rd=(Rd*) ((U32)e-(U32)&rd->ethernet[0]); rd->commandStatus->all=0; rd->sizes->all=0; rd->sizes->size=Ethernet::MTU; asm("wbinvd"); ifdebug(8) { debug<<"Fei82559 receive "<< (U32)rd->ethernet << "\r\n"; } } Ethernet *Fei82559::send() { Td* td; td=(Td*)(U32)currentTd->link; asm("invd"); if(!td->commandStatus->c) { ifdebug(8) { debug<<"Fei82559 send\r\n"; } return 0; } td->commandStatus->all=0; asm("wbinvd"); ifdebug(8) { debug<<"Fei82559 send "<< (U32)td->ethernet <<"\r\n"; } return td->ethernet; } bool Fei82559::send(Ethernet *e,U32 size) { Td* td=0; td=(Td*) ((U32)e-(U32)&td->ethernet[0]); ifdebug(8) { debug<<"Fei82559 send "<< (U32)td->ethernet << ' ' << size << "\r\n"; } td->commandStatus->s=1; td->commandStatus->cmd=4; //td->link=0; td->tbds=(Hw::Tbd*)~0; td->sizes->all=0; td->sizes->eof=1; td->sizes->threshold=1; td->sizes->tcbCount=size; currentTd->commandStatus->s=0; asm("wbinvd"); currentTd=td; hw->doCuResume(); while(1) { asm("invd"); if(td->commandStatus->c) break; } return true; } /* int a[]= { sizeof(Fei82559::Hw::Cb), sizeof(Fei82559::Hw::Td), sizeof(Fei82559::Td) }; */