/*
* $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.bus.ide;
import org.apache.log4j.Logger;
import org.jnode.util.Command;
import org.jnode.util.TimeUtils;
import org.jnode.util.TimeoutException;
/**
* @author epr
*/
public abstract class IDECommand extends Command implements IDEConstants {
protected static final Logger log = Logger.getLogger(IDECommand.class);
/**
* ID From master (true) or slave (false)
*/
protected final boolean master;
/**
* The taskfile for which this command is intended
*/
private final boolean primary;
/**
* Error that occurred during this command. -1 means no error
*/
private int error = -1;
/**
* Create a new instance
*
* @param master Command intended for master (true) or slave (false)
* @throws IllegalArgumentException Invalid argument
*/
protected IDECommand(boolean primary, boolean master)
throws IllegalArgumentException {
this.primary = primary;
this.master = master;
}
/**
* Setup the IDE controller for this command
*/
protected abstract void setup(IDEBus ide, IDEIO io) throws TimeoutException;
/**
* Handle an IDE IRQ.
*/
protected abstract void handleIRQ(IDEBus ide, IDEIO io)
throws TimeoutException;
/**
* Is this command for the master (true) or slave (false).
*
* @return if this command is for the master
*/
public final boolean isMaster() {
return master;
}
/**
* Is this command intended for the primary channel.
*
* @return if this command is intended for the primary channel
*/
public final boolean isPrimary() {
return primary;
}
/**
* Is this command intended for the secondary channel.
*
* @return if this command is intended for the secondary channel
*/
public final boolean isSecondary() {
return !primary;
}
/**
* Has this command got an error?
*
* @return if this command got an error
*/
public final boolean hasError() {
return (error != -1);
}
/**
* Gets the error code that occurred during this command
*
* @return the error code that occurred during this command
*/
public final int getError() {
return error;
}
/**
* Set the error code.
* This also notifies this command as being finished.
*
* @param error
*/
protected void setError(int error) {
this.error = error;
notifyFinished();
}
/**
* Gets the value for the select register.
*
* @return the value for the select register
*/
protected final int getSelect() {
if (master) {
return SEL_BLANK | SEL_DRIVE_MASTER;
} else {
return SEL_BLANK | SEL_DRIVE_SLAVE;
}
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
return getClass().getName() + " " + (primary ? "primary" : "secondary")
+ "." + (master ? "master" : "slave");
}
/**
* Perform the device selection protocol.
* See: ATA/ATAPI-4 9.6
*
* @throws TimeoutException
*/
protected void selectDevice(IDEIO io) throws TimeoutException {
final int mask = ST_BUSY | ST_DATA_REQUEST;
io.waitUntilStatus(mask, 0, IDE_TIMEOUT, null);
// Write the Device/Head register with appropriate DEV bit value
io.setSelectReg(getSelect());
// Wait at least 400ns
TimeUtils.sleep(1);
io.waitUntilStatus(mask, 0, IDE_TIMEOUT, null);
}
/**
* Flush the write cache.
*
* @throws TimeoutException
*/
protected void flushCache(IDEIO io, boolean is48bit) throws TimeoutException {
io.setCommandReg(is48bit ? CMD_FLUSH_CACHE_EXT : CMD_FLUSH_CACHE);
io.waitUntilStatus(ST_BUSY, 0, IDE_TIMEOUT, "flushCache");
}
}