Package org.jnode.driver.bus.ide

Source Code of org.jnode.driver.bus.ide.DefaultIDEIO

/*
* $Id$
*
* Copyright (C) 2003-2014 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 java.security.PrivilegedExceptionAction;
import javax.naming.NameNotFoundException;
import org.apache.log4j.Logger;
import org.jnode.driver.Device;
import org.jnode.driver.DriverException;
import org.jnode.driver.bus.pci.PCIBaseAddress;
import org.jnode.driver.bus.pci.PCIDevice;
import org.jnode.driver.bus.pci.PCIDeviceConfig;
import org.jnode.naming.InitialNaming;
import org.jnode.system.resource.IOResource;
import org.jnode.system.resource.ResourceManager;
import org.jnode.system.resource.ResourceNotFreeException;
import org.jnode.system.resource.ResourceOwner;
import org.jnode.util.AccessControllerUtils;
import org.jnode.util.NumberUtils;
import org.jnode.util.TimeUtils;
import org.jnode.util.TimeoutException;


/**
* IDE IO-port accessor.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class DefaultIDEIO implements IDEIO {

    /**
     * My logger
     */
    private static final Logger log = Logger.getLogger(DefaultIDEIO.class);

    /**
     * IDE Taskfile io space
     */
    private IOResource cmdBlock;

    /**
     * IDE High taskfile io space
     */
    private IOResource ctrlBlock;

    /**
     * First port address of command block
     */
    private final int cmdBlockStart;

    /**
     * First port address of control block
     */
    private final int ctrlBlockStart;

    /**
     * Port number of AltStatus register
     */
    private final int altStatusPort;

    /**
     * IRQ number to respond to
     */
    private final int irq;

    /**
     * Create a new instance
     */
    protected DefaultIDEIO(Device device, boolean primary)
        throws IllegalArgumentException, DriverException, ResourceNotFreeException {

        int cmdBlockStart = (primary ? IDE0_START_PORT : IDE1_START_PORT);
        int ctrlBlockStart = cmdBlockStart + HIGH_OFFSET;
        int cmdBlockSize = IDE_NR_PORTS;
        int ctrlBlockSize = IDE_NR_HIGH_PORTS;
        int altStatusPort = ctrlBlockStart + R8_ALTSTATUS_OFFSET;
        int irq = (primary ? IDE0_IRQ : IDE1_IRQ);
        boolean nativeMode = false;

        // Detect PCI IDE Controller, look for enhanced mode
        if (device instanceof PCIDevice) {
            final PCIDevice pciDev = (PCIDevice) device;
            final PCIDeviceConfig pciCfg = pciDev.getConfig();
            final int pIntf = pciCfg.getMinorClass();
            final int progMask = 0x02 | 0x08;
            final int enhModeMask = 0x01 | 0x04;
            if ((pIntf & progMask) == progMask) {
                // Mode is programmable, set enhanced mode
                //pciCfg.setMinorClass(pIntf | enhModeMask);               
            }
            if ((pciCfg.getMinorClass() & enhModeMask) == enhModeMask) {
                // Use enhanced mode
                final PCIBaseAddress[] baseAddrs = pciCfg.asHeaderType0().getBaseAddresses();
                final int idx = (primary ? 0 : 2);
                cmdBlockStart = baseAddrs[idx].getIOBase();
                cmdBlockSize = 8;
                ctrlBlockStart = baseAddrs[idx + 1].getIOBase();
                ctrlBlockSize = 4;
                altStatusPort = ctrlBlockStart + 0x02;
                irq = pciCfg.asHeaderType0().getInterruptLine();
                nativeMode = true;
            }
        }

        log.info("Using PCI IDE " + (nativeMode ? "Native" : "Compatibility") + " mode [irq=" + irq + "]");

        // Now claim the resources
        IOResource cmdBlock = null;
        IOResource ctrlBlock = null;
        final ResourceManager rm;
        try {
            rm = InitialNaming.lookup(ResourceManager.NAME);
            cmdBlock = claimPorts(rm, device, cmdBlockStart, cmdBlockSize);
            ctrlBlock = claimPorts(rm, device, ctrlBlockStart, ctrlBlockSize);
        } catch (NameNotFoundException ex) {
            throw new ResourceNotFreeException("Cannot find ResourceManager",
                ex);
        } catch (ResourceNotFreeException ex) {
            if (cmdBlock != null) {
                cmdBlock.release();
            }
            if (ctrlBlock != null) {
                ctrlBlock.release();
            }
            throw ex;
        }
        this.irq = irq;
        this.cmdBlockStart = cmdBlockStart;
        this.ctrlBlockStart = ctrlBlockStart;
        this.cmdBlock = cmdBlock;
        this.ctrlBlock = ctrlBlock;
        this.altStatusPort = altStatusPort;
    }

    /**
     * Stop this processor.
     */
    public void release() {
        cmdBlock.release();
        ctrlBlock.release();
    }

    /**
     * Gets a word from the data register
     *
     * @return a word from the data register
     */
    public final int getDataReg() {
        return cmdBlock.inPortWord(cmdBlockStart + RW16_DATA_OFFSET);
    }

    /**
     * Writes a word to the data register
     *
     * @param dataWord
     */
    public final void setDataReg(int dataWord) {
        cmdBlock.outPortWord(cmdBlockStart + RW16_DATA_OFFSET, dataWord);
    }

    /**
     * Gets the contents of the error register
     *
     * @return the contents of the error register
     */
    public final int getErrorReg() {
        return cmdBlock.inPortByte(cmdBlockStart + R8_ERROR_OFFSET);
    }

    /**
     * Sets the contents of the featureregister
     *
     * @param features
     */
    public final void setFeatureReg(int features) {
        cmdBlock.outPortByte(cmdBlockStart + W8_FEATURE_OFFSET, features);
    }

    /**
     * Gets the contents of the sector count register
     *
     * @return the contents of the sector count register
     */
    public final int getSectorCountReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_SECTOR_COUNT_OFFSET);
    }

    /**
     * Sets the sector count register
     *
     * @param sectorCount
     */
    public final void setSectorCountReg(int sectorCount) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_SECTOR_COUNT_OFFSET, sectorCount);
    }

    /**
     * Gets the contents of the sector register
     *
     * @return the contents of the sector register
     */
    public final int getSectorReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_SECTOR_OFFSET);
    }

    /**
     * Gets the contents of the LBA low register
     *
     * @return the contents of the LBA low register
     */
    public final int getLbaLowReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_LBA_LOW_OFFSET);
    }

    /**
     * Gets the contents of the LBA mid register
     *
     * @return the contents of the LBA mid register
     */
    public final int getLbaMidReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_LBA_MID_OFFSET);
    }

    /**
     * Gets the contents of the LBA high register
     *
     * @return the contents of the LBA high register
     */
    public final int getLbaHighReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_LBA_HIGH_OFFSET);
    }

    /**
     * Sets the contents of the LBA low register
     *
     * @param value
     */
    public final void setLbaLowReg(int value) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_LBA_LOW_OFFSET, value);
    }

    /**
     * Sets the contents of the LBA mid register
     *
     * @param value
     */
    public final void setLbaMidReg(int value) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_LBA_MID_OFFSET, value);
    }

    /**
     * Sets the contents of the LBA high register
     *
     * @param value
     */
    public final void setLbaHighReg(int value) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_LBA_HIGH_OFFSET, value);
    }

    /**
     * Sets the sector register
     *
     * @param sector
     */
    protected final void setSectorReg(int sector) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_SECTOR_OFFSET, sector);
    }

    /**
     * Gets the combined cylinder value out the the cylinder LSB and MSB
     * registers.
     */
    protected final int getCylinderRegs() {
        final int lsb = cmdBlock.inPortByte(cmdBlockStart + RW8_CYLINDER_LSB_OFFSET);
        final int msb = cmdBlock.inPortByte(cmdBlockStart + RW8_CYLINDER_MSB_OFFSET);
        return ((msb & 0xFF) << 8) | (lsb & 0xFF);
    }

    /**
     * Sets the cylinder registers value (both LSB and MSB)
     */
    protected final void setCylinderRegs(int cylinder) {
        final int lsb = cylinder & 0xFF;
        final int msb = (cylinder >> 8) & 0xFF;
        cmdBlock.outPortByte(cmdBlockStart + RW8_CYLINDER_LSB_OFFSET, lsb);
        cmdBlock.outPortByte(cmdBlockStart + RW8_CYLINDER_MSB_OFFSET, msb);
    }

    /**
     * Gets the contents of the select register
     *
     * @return the contents of the select register
     */
    public final int getSelectReg() {
        return cmdBlock.inPortByte(cmdBlockStart + RW8_SELECT_OFFSET);
    }

    /**
     * Sets the select register
     *
     * @param select
     */
    public final void setSelectReg(int select) {
        cmdBlock.outPortByte(cmdBlockStart + RW8_SELECT_OFFSET, select);
    }

    /**
     * Gets the status of the IDE controller. Any pending IRQ is reset.
     *
     * @return the status of the IDE controller. Any pending IRQ is reset.
     */
    public final int getStatusReg() {
        return cmdBlock.inPortByte(cmdBlockStart + R8_STATUS_OFFSET);
    }

    /**
     * Gets the alternative status of the IDE controller. Any pending IRQ is
     * NOT reset.
     *
     * @return the alternative status of the IDE controller
     */
    public final int getAltStatusReg() {
        return ctrlBlock.inPortByte(altStatusPort);
    }

    /**
     * Sets the command register. This also activates the IDE controller so
     * always set other registers first.
     *
     * @param command
     */
    public final void setCommandReg(int command) {
        cmdBlock.outPortByte(cmdBlockStart + W8_COMMAND_OFFSET, command);
    }

    /**
     * Sets the control register.
     *
     * @param control The new value for the control register
     */
    public final void setControlReg(int control) {
        ctrlBlock.outPortByte(ctrlBlockStart + W8_CONTROL_OFFSET, control);
    }

    /**
     * Is this channel busy.
     *
     * @return if this channel is busy
     */
    public final boolean isBusy() {
        return ((getAltStatusReg() & ST_BUSY) == ST_BUSY);
    }

    /**
     * Block the current thread until the status of the controller masked by the given mask equals value.
     */
    public void waitUntilStatus(int mask, int value, long timeout, String message) throws TimeoutException {
        while ((getAltStatusReg() & mask) != value) {
            final int state = getAltStatusReg();
            if ((state & ST_ERROR) != 0) {
                throw new TimeoutException("IDE error " + NumberUtils.hex(getErrorReg(), 2));
            }
            if (timeout <= 0) {
                throw new TimeoutException((message != null) ? message : "Timeout in waitUntilStatus");
            }
            TimeUtils.sleep(10);
            timeout -= 10;
        }
    }

    private IOResource claimPorts(final ResourceManager rm,
                                  final ResourceOwner owner, final int low, final int length)
        throws ResourceNotFreeException, DriverException {
        try {
            return AccessControllerUtils.doPrivileged(new PrivilegedExceptionAction<IOResource>() {
                public IOResource run() throws ResourceNotFreeException {
                    return rm.claimIOResource(owner, low, length);
                }
            });
        } catch (ResourceNotFreeException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new DriverException("Unknown exception", ex);
        }
    }

    /**
     * @return Returns the irq.
     */
    public final int getIrq() {
        return this.irq;
    }
}
TOP

Related Classes of org.jnode.driver.bus.ide.DefaultIDEIO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.