1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
 
21
package org.jnode.vm;
22
23
import org.jnode.system.IOResource;
24
import org.jnode.system.Resource;
25
import org.jnode.system.ResourceNotFreeException;
26
import org.jnode.system.ResourceOwner;
27
import org.jnode.util.NumberUtils;
28
29
30
/**
31
 * Default implementation of IOResource.
32
 *
33
 * @author Ewout Prangsma (epr@users.sourceforge.net)
34
 */
35
final class IOResourceImpl extends Region implements IOResource {
36
37
    /**
38
     * The first port of this resource
39
     */
40
    private int startPort;
41
    /**
42
     * The length of the port region
43
     */
44
    private int length;
45
    /**
46
     * Has this resource been released?
47
     */
48
    private boolean released;
49
    /**
50
     * The list of active IOResource's
51
     */
52
    private static Region resources;
53
54
    /**
55
     * Create a new instance
56
     *
57
     * @param owner
58
     * @param startPort
59
     * @param length
60
     */
61
    private IOResourceImpl(ResourceOwner owner, int startPort, int length) {
62
        super(owner);
63
        this.startPort = startPort;
64
        this.length = length;
65
        this.released = false;
66
    }
67
68
    /**
69
     * Claim a range of IO ports
70
     *
71
     * @param owner
72
     * @param startPort
73
     * @param length
74
     * @return The claimed resource
75
     * @throws ResourceNotFreeException
76
     */
77
    protected static synchronized IOResource claimIOResource(ResourceOwner owner, int startPort, int length)
78
        throws ResourceNotFreeException {
79
        final IOResourceImpl res = new IOResourceImpl(owner, startPort, length);
80
        if (isFree(resources, res)) {
81
            resources = add(resources, res);
82
            return res;
83
        } else {
84
            final Object curOwner = get(resources, res).getOwner();
85
            throw new ResourceNotFreeException("port " + NumberUtils.hex(startPort) + "-" +
86
                NumberUtils.hex(startPort + length - 1) + " is owned by " + curOwner);
87
        }
88
    }
89
90
    /**
91
     * Returns the length.
92
     *
93
     * @return int
94
     */
95
    public int getLength() {
96
        return length;
97
    }
98
99
    /**
100
     * Returns the startPort.
101
     *
102
     * @return int
103
     */
104
    public int getStartPort() {
105
        return startPort;
106
    }
107
108
    public int inPortByte(int portNr) {
109
        testPort(portNr, 1);
110
        return Unsafe.inPortByte(portNr);
111
    }
112
113
    public int inPortWord(int portNr) {
114
        testPort(portNr, 2);
115
        return Unsafe.inPortWord(portNr);
116
    }
117
118
    public int inPortDword(int portNr) {
119
        testPort(portNr, 4);
120
        return Unsafe.inPortDword(portNr);
121
    }
122
123
    public void outPortByte(int portNr, int value) {
124
        testPort(portNr, 1);
125
        Unsafe.outPortByte(portNr, value);
126
    }
127
128
    public void outPortWord(int portNr, int value) {
129
        testPort(portNr, 2);
130
        Unsafe.outPortWord(portNr, value);
131
    }
132
133
    public void outPortDword(int portNr, int value) {
134
        testPort(portNr, 4);
135
        Unsafe.outPortDword(portNr, value);
136
    }
137
138
    /**
139
     * Compare to regions.
140
     *
141
     * @param otherRegion
142
     * @return a negative integer, zero, or a positive integer as
143
     *         this object is less than, equal to, or greater than the
144
     *         specified region. If the regions overlap, 0 is returned.
145
     */
146
    public int compareTo(Region otherRegion) {
147
        final IOResourceImpl other = (IOResourceImpl) otherRegion;
148
        if (this.startPort + this.length <= other.startPort) {
149
            return -1;
150
        } else if (this.startPort >= other.startPort + other.length) {
151
            return 1;
152
        } else {
153
            return 0;
154
        }
155
156
    }
157
158
    /**
159
     * Give up this resource. After this method has been called, the resource
160
     * cannot be used anymore.
161
     */
162
    public void release() {
163
        if (!this.released) {
164
            this.released = true;
165
            synchronized (getClass()) {
166
                resources = remove(resources, this);
167
            }
168
        }
169
    }
170
171
    /**
172
     * Gets the parent resource if any.
173
     *
174
     * @return The parent resource, or null if this resource has no parent.
175
     */
176
    public Resource getParent() {
177
        return null;
178
    }
179
180
    private void testPort(int portNr, int size) {
181
        if (released) {
182
            throw new IndexOutOfBoundsException("Resource is released");
183
        }
184
        if ((portNr < startPort) || ((portNr + size) > (startPort + length))) {
185
            throw new IndexOutOfBoundsException();
186
        }
187
    }
188
}