irqmanager.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 234 行

JAVA
234
字号
/*
 * $Id: IRQManager.java,v 1.2 2003/12/02 19:08:33 epr Exp $
 */
package org.jnode.vm;

import javax.naming.NameNotFoundException;

import org.jnode.naming.InitialNaming;
import org.jnode.system.IOResource;
import org.jnode.system.IRQHandler;
import org.jnode.system.IRQResource;
import org.jnode.system.ResourceManager;
import org.jnode.system.ResourceNotFreeException;
import org.jnode.system.ResourceOwner;
import org.jnode.system.SimpleResourceOwner;

/**
 * IRQ manager implementation.
 * 
 * @author epr
 */
public final class IRQManager {

	private final Object LOCK = new Object();
	private final ResourceOwner IRQ_MANAGER = new SimpleResourceOwner("system");
	private final IRQThread[] handlers;
	private final IOResource io8259_A;
	private final IOResource io8259_B;
	private final int count;
	private final int[] irqCount;

	/**
	 * Initialize a new instance
	 * 
	 * @param irqCount
	 */
	IRQManager(int[] irqCount) {
		this.irqCount = irqCount;
		this.count = irqCount.length;
		this.handlers = new IRQThread[count];
		try {
			final ResourceManager rm = (ResourceManager) InitialNaming.lookup(ResourceManager.NAME);
			io8259_A = rm.claimIOResource(IRQ_MANAGER, 0x20, 1); // 0xA0
			io8259_B = rm.claimIOResource(IRQ_MANAGER, 0xA0, 1);
		} catch (NameNotFoundException ex) {
			throw new Error("Cannot find ResourceManager", ex);
		} catch (ResourceNotFreeException ex) {
			throw new Error("Cannot claim PIC0-IO ports", ex);
		}
	}

	/**
	 * Gets the IRQ counter value for the given IRQ
	 * @param irq
	 * @return The irq count
	 */
	public final int getIrqCount(int irq) {
		return irqCount[irq];
	}

	/**
	 * Gets the number of IRQ's this processor supports.
	 * @return int
	 */
	public final int getNumIRQs() {
		return count;
	}

	public Object getHandlerInfo(int irq) {
		return handlers[irq];
	}

	/**
	 * Register an interrupt handler for a given irq number.
	 * 
	 * @param owner
	 * @param irq
	 * @param handler
	 * @param shared
	 * @return True is the handler was set, false if there was already a handler for the given irq
	 *         number set.
	 * @throws ResourceNotFreeException
	 */
	final IRQResource claimIRQ(ResourceOwner owner, int irq, IRQHandler handler, boolean shared) throws ResourceNotFreeException {
		synchronized (LOCK) {
			if (handlers[irq] == null) {
				IRQThread thread = new IRQThread(this, irq, owner, handler, shared);
				thread.start();
				handlers[irq] = thread;
				return new IRQResourceImpl(owner, irq, handler, shared);
			} else {
				final IRQThread thread = handlers[irq];
				if (thread.isShared()) {
					if (shared) {
						thread.addHandler(owner, handler);
						return new IRQResourceImpl(owner, irq, handler, shared);
					} else {
						throw new ResourceNotFreeException("IRQ " + irq + " is already claimed, but you don't want to share");
					}
				} else {
					if (shared) {
						throw new ResourceNotFreeException("IRQ " + irq + " is already claimed, but not shared");
					} else {
						//Unsafe.debug("IRQ was already claim");
						throw new ResourceNotFreeException("IRQ " + irq + " is not free");
					}
				}
			}
		}
	}

	/**
	 * Unregister a given interrupt handler for a given irq number. If the current handler for the
	 * given irq number is not equal to the given handler, nothing is done.
	 * 
	 * @param res
	 *            The IRQ resource
	 */
	final void releaseIRQ(IRQResourceImpl res) {
		final int irq = res.getIRQ();
		synchronized (LOCK) {
			final IRQThread thread = handlers[irq];
			if (thread != null) {
				thread.remove(res.getHandler());
				if (thread.isEmpty()) {
					handlers[irq] = null;
					thread.stopThread();
				}
			}
		}
	}

	/**
	 * Dispatch IRQ events to their corresponding threads. This method should only be called by the
	 * Thread scheduler.
	 * @param current
	 * @throws PragmaUninterruptible
	 */
	final void dispatchInterrupts(VmThread current) throws PragmaUninterruptible {
		final IRQThread[] hlist = handlers;
		final int[] irqCount = this.irqCount;
		final int max = this.count;
		for (int irq = 0; irq < max; irq++) {
			final IRQThread thread = hlist[irq];
			if (thread != null) {
				thread.signalIRQ(irqCount[irq], current);
			} else {
				// No handler, signal and End of Interrupt
				eoi(irq);
			}
		}
	}

	/**
	 * Set an End Of Interrupt message to the 8259 interrupt controller(s).
	 * 
	 * @param irq
	 * @throws PragmaUninterruptible
	 */
	final void eoi(int irq) throws PragmaUninterruptible {
		if (irq < 8) {
			io8259_A.outPortByte(0x20, 0x60 + irq);
		} else {
			/*
			 * if (irq == 10) { Screen.debug(" <EOI 10/> ");
			 */
			io8259_B.outPortByte(0xA0, 0x60 + irq - 8);
			/* EOI of cascade */
			io8259_A.outPortByte(0x20, 0x60 + 2);
		}
	}

	final class IRQResourceImpl implements IRQResource {

		/** The owner of this resource */
		private final ResourceOwner owner;
		/** The IRQ number */
		private final int irq;
		/** The handler */
		private final IRQHandler handler;
		private final boolean shared;

		/**
		 * Create a new instance
		 * 
		 * @param owner
		 * @param irq
		 * @param handler
		 * @param shared
		 */
		public IRQResourceImpl(ResourceOwner owner, int irq, IRQHandler handler, boolean shared) {
			this.owner = owner;
			this.irq = irq;
			this.handler = handler;
			this.shared = shared;
		}

		/**
		 * @see org.jnode.system.IRQResource#getIRQ()
		 * @return int
		 */
		public int getIRQ() {
			return irq;
		}

		/**
		 * Is this a shared interrupt?
		 * @return boolean
		 */
		public boolean isShared() {
			return shared;
		}

		/**
		 * @see org.jnode.system.Resource#getOwner()
		 * @return The owner
		 */
		public ResourceOwner getOwner() {
			return owner;
		}

		public IRQHandler getHandler() {
			return handler;
		}

		/**
		 * @see org.jnode.system.Resource#release()
		 */
		public void release() {
			releaseIRQ(this);
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?