/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.net.eepro100;
import org.apache.log4j.Logger;
import org.jnode.driver.net.NetworkException;
import org.jnode.net.SocketBuffer;
import org.jnode.system.resource.ResourceManager;
import org.jnode.util.NumberUtils;
/**
* @author flesire
*/
public class EEPRO100Buffer implements EEPRO100Constants {
//---
protected final Logger log = Logger.getLogger(getClass());
private ResourceManager rm;
private EEPRO100Registers regs;
private EEPRO100RxFD rxPacket;
private EEPRO100TxFD txFD;
// --- Rx Variables
private int rxMode;
private int curRx;
private int dirtyRx;
public EEPRO100RxFD[] rxRing = new EEPRO100RxFD[RX_RING_SIZE];
// --- Tx Variables
private int txThreshold = 0x01200000;
private int curTx;
private int dirtyTx;
public EEPRO100TxFD[] txRing = new EEPRO100TxFD[TX_RING_SIZE];
@SuppressWarnings("unused")
private EEPRO100TxFD lastCmd;
public EEPRO100Buffer(EEPRO100Registers regs, ResourceManager rm) {
this.regs = regs;
this.rm = rm;
curTx = 0;
dirtyTx = 0;
}
/**
*
*
*/
public final void initSingleRxRing() {
/* Base = 0 */
regs.setReg32(SCBPointer, 0);
regs.setReg16(SCBCmd, SCBMaskAll | RxAddrLoad);
regs.waitForCmdDone();
log.debug("Set RX base addr.");
rxPacket = new EEPRO100RxFD(rm);
rxPacket.setStatus(0x0001);
rxPacket.setCommand(0x0000);
rxPacket.setLink(rxPacket.getStatus());
// TODO Set correct value
rxPacket.setRxBufferAddress(0);
// ---------------------------------
rxPacket.setCount(0);
rxPacket.setSize(1528);
rxPacket.initialize();
regs.setReg32(SCBPointer, rxPacket.getBufferAddress());
regs.setReg16(SCBCmd, SCBMaskAll | RxStart);
regs.waitForCmdDone();
log.debug("Started rx process.");
// Start the receiver.
rxPacket.setStatus(0);
rxPacket.setCommand(0xC000);
regs.setReg32(SCBPointer, rxPacket.getBufferAddress());
regs.setReg16(SCBCmd, SCBMaskAll | RxStart);
}
/**
*
*
*/
public final void initSingleTxRing() {
regs.waitForCmdDone();
log.debug("Set TX base addr.");
txFD = new EEPRO100TxFD(rm);
txFD.setCommand(CmdIASetup);
txFD.setStatus(0x0000);
txFD.setCount(0x02208000);
txFD.setLink(txFD.getFirstDPDAddress().toInt());
txFD.setDescriptorAddress(txFD.getBufferAddress());
}
/**
* @param buf
*/
public void transmit(SocketBuffer buf) {
int status;
int s1;
int s2;
status = regs.getReg16(SCBStatus);
/* Acknowledge all of the current interrupt sources ASAP. */
regs.setReg16(SCBStatus, status & IntrAllNormal);
log.debug("transmitting status = " + NumberUtils.hex(status) + ", cmd=" +
NumberUtils.hex(regs.getReg16(SCBStatus)) + '\n');
txFD.setStatus(0);
txFD.setCommand(CmdSuspend | CmdTx | CmdTxFlex);
txFD.setLink(txFD.getFirstDPDAddress().toInt());
txFD.setCount(0x02208000);
log.debug("Tx FD :\n" + txFD.toString());
txFD.initialize(buf);
log.debug("Tx FD 2:\n" + txFD.toString());
regs.setReg16(SCBPointer, txFD.getBufferAddress());
regs.setReg16(SCBCmd, SCBMaskAll | CUStart);
regs.waitForCmdDone();
s1 = regs.getReg16(SCBStatus);
// TODO wait 10 ms for transmiting;
long start = System.currentTimeMillis();
while ((System.currentTimeMillis() <= start + 10) && (txFD.getStatus() != 0)) {
// FIXME ... busy wait!!!!
}
s2 = regs.getReg16(SCBStatus);
log.debug("Tx FD :");
log.debug(txFD.toString());
log.debug("s1=" + NumberUtils.hex(s1) + " s2=" + NumberUtils.hex(s2));
}
/**
* @param driver
*/
public void poll(EEPRO100Driver driver) throws NetworkException {
log.debug("*** RX packet status : " + rxPacket.getStatus());
if (rxPacket.getStatus() != 0) {
// Got a packet, restart the receiver
rxPacket.setStatus(0);
rxPacket.setCommand(0xc000);
regs.setReg16(SCBPointer, rxPacket.getStatus());
regs.setReg16(SCBCmd, SCBMaskAll | RxStart);
regs.waitForCmdDone();
log.debug("Got a packet: Len=" + NumberUtils.hex(rxPacket.getCount()));
final SocketBuffer skbuf = rxPacket.getPacket();
driver.onReceive(skbuf);
}
}
/**
*
*
*/
public void txProcess() {
// Caution: the write order is important here, set the base address with
// the "ownership" bits last.
// Prevent interrupts from changing the Tx ring from underneath us.
/* Calculate the Tx descriptor entry. */
int txEntry = getCurTx() & TX_RING_SIZE - 1;
txRing[txEntry].setStatus(0);
txRing[txEntry].setCommand(CmdSuspend | CmdTx | CmdTxFlex);
getNextTx();
txRing[txEntry].setLink(txRing[getCurTx() & TX_RING_SIZE - 1].getBufferAddress());
// We may nominally release the lock here.
txRing[txEntry].setDescriptorAddress(txRing[txEntry].getBufferAddress() + 16);
// The data region is always in one buffer descriptor.
txRing[txEntry].setCount(getTxThreshold());
// EEPRO100TxFD lastCmd0 = lastCmd;
lastCmd = txRing[txEntry];
regs.waitForCmdDone();
regs.setReg8(SCBCmd, CUResume);
}
// --- Accessors ---
/**
* @return Returns the curRx.
*/
public int getCurRx() {
return curRx;
}
/**
* @param curRx The curRx to set.
*/
public void setCurRx(int curRx) {
this.curRx = curRx;
}
/**
* @return Returns the curTx.
*/
public int getCurTx() {
return curTx;
}
/**
* @return Returns the next Tx.
*/
public int getNextTx() {
return curTx++;
}
/**
* @param curTx The curTx to set.
*/
public void setCurTx(int curTx) {
this.curTx = curTx;
}
/**
* @return Returns the dirtyRx.
*/
public int getDirtyRx() {
return dirtyRx;
}
/**
* @param dirtyRx The dirtyRx to set.
*/
public void setDirtyRx(int dirtyRx) {
this.dirtyRx = dirtyRx;
}
/**
* @return Returns the dirtyTx.
*/
public int getDirtyTx() {
return dirtyTx;
}
/**
* @param dirtyTx The dirtyTx to set.
*/
public void setDirtyTx(int dirtyTx) {
this.dirtyTx = dirtyTx;
}
/**
* @return Returns the txThreshold.
*/
public int getTxThreshold() {
return txThreshold;
}
/**
* @param txThreshold The txThreshold to set.
*/
public void setTxThreshold(int txThreshold) {
this.txThreshold = txThreshold;
}
/**
* @return Returns the rxMode.
*/
public int getRxMode() {
return rxMode;
}
/**
* @param rxMode The rxMode to set.
*/
public void setRxMode(int rxMode) {
this.rxMode = rxMode;
}
}