intel_8254_timer.hh revision 7559:017baf09599f
1/*
2 * Copyright (c) 2004, 2005
3 * The Regents of The University of Michigan
4 * All Rights Reserved
5 *
6 * This code is part of the M5 simulator.
7 *
8 * Permission is granted to use, copy, create derivative works and
9 * redistribute this software and such derivative works for any
10 * purpose, so long as the copyright notice above, this grant of
11 * permission, and the disclaimer below appear in all copies made; and
12 * so long as the name of The University of Michigan is not used in
13 * any advertising or publicity pertaining to the use or distribution
14 * of this software without specific, written prior authorization.
15 *
16 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
17 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
18 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
19 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
22 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
23 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
24 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
25 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
26 * DAMAGES.
27 *
28 * Authors: Ali G. Saidi
29 *          Andrew L. Schultz
30 *          Miguel J. Serrano
31 */
32
33#ifndef __DEV_8254_HH__
34#define __DEV_8254_HH__
35
36#include <string>
37#include <iostream>
38
39#include "base/bitunion.hh"
40#include "base/types.hh"
41#include "sim/eventq.hh"
42#include "sim/serialize.hh"
43
44/** Programmable Interval Timer (Intel 8254) */
45class Intel8254Timer : public EventManager
46{
47  protected:
48    BitUnion8(CtrlReg)
49        Bitfield<7, 6> sel;
50        Bitfield<5, 4> rw;
51        Bitfield<3, 1> mode;
52        Bitfield<0> bcd;
53    EndBitUnion(CtrlReg)
54
55    enum SelectVal {
56        SelectCounter0,
57        SelectCounter1,
58        SelectCounter2,
59        ReadBackCommand
60    };
61
62    enum ReadWriteVal {
63        LatchCommand,
64        LsbOnly,
65        MsbOnly,
66        TwoPhase
67    };
68
69    enum ModeVal {
70        InitTc,
71        OneShot,
72        RateGen,
73        SquareWave,
74        SoftwareStrobe,
75        HardwareStrobe
76    };
77
78    /** Counter element for PIT */
79    class Counter
80    {
81        /** Event for counter interrupt */
82        class CounterEvent : public Event
83        {
84          private:
85            /** Pointer back to Counter */
86            Counter* counter;
87            Tick interval;
88
89          public:
90            CounterEvent(Counter*);
91
92            /** Event process */
93            void process();
94
95            /** Event description */
96            virtual const char *description() const;
97
98            friend class Counter;
99
100            void setTo(int clocks);
101
102            int clocksLeft();
103        };
104
105      private:
106        std::string _name;
107        const std::string &name() const { return _name; }
108
109        unsigned int num;
110
111        CounterEvent event;
112
113        /** Initial count value */
114        uint16_t initial_count;
115
116        /** Latched count */
117        uint16_t latched_count;
118
119        /** Interrupt period */
120        uint16_t period;
121
122        /** Current mode of operation */
123        uint8_t mode;
124
125        /** Output goes high when the counter reaches zero */
126        bool output_high;
127
128        /** State of the count latch */
129        bool latch_on;
130
131        /** Set of values for read_byte and write_byte */
132        enum {LSB, MSB};
133
134        /** Determine which byte of a 16-bit count value to read/write */
135        uint8_t read_byte, write_byte;
136
137        /** Pointer to container */
138        Intel8254Timer *parent;
139
140        /** if non-zero, the scheduled tick of an event used for drain
141            serialization coordination */
142        Tick event_tick;
143
144      public:
145        Counter(Intel8254Timer *p, const std::string &name, unsigned int num);
146
147        /** Latch the current count (if one is not already latched) */
148        void latchCount();
149
150        /** Get the current count for this counter */
151        int currentCount();
152
153        /** Set the read/write mode */
154        void setRW(int rw_val);
155
156        /** Set operational mode */
157        void setMode(int mode_val);
158
159        /** Set count encoding */
160        void setBCD(int bcd_val);
161
162        /** Read a count byte */
163        uint8_t read();
164
165        /** Write a count byte */
166        void write(const uint8_t data);
167
168        /** Is the output high? */
169        bool outputHigh();
170
171        /**
172         * Drain all associated events.
173         * @param drainEvent
174         */
175        unsigned int drain(Event *de);
176
177        /**
178         * Serialize this object to the given output stream.
179         * @param base The base name of the counter object.
180         * @param os   The stream to serialize to.
181         */
182        void serialize(const std::string &base, std::ostream &os);
183
184        /**
185         * Reconstruct the state of this object from a checkpoint.
186         * @param base The base name of the counter object.
187         * @param cp The checkpoint use.
188         * @param section The section name of this object
189         */
190        void unserialize(const std::string &base, Checkpoint *cp,
191                         const std::string &section);
192    };
193
194  protected:
195    std::string _name;
196    const std::string &name() const { return _name; }
197
198    /** PIT has three seperate counters */
199    Counter *counter[3];
200
201    virtual void
202    counterInterrupt(unsigned int num)
203    {
204        DPRINTF(Intel8254Timer, "Timer interrupt from counter %d.\n", num);
205    }
206
207  public:
208
209    virtual
210    ~Intel8254Timer()
211    {}
212
213    Intel8254Timer(EventManager *em, const std::string &name,
214            Counter *counter0, Counter *counter1, Counter *counter2);
215
216    Intel8254Timer(EventManager *em, const std::string &name);
217
218    /** Write control word */
219    void writeControl(const CtrlReg data);
220
221    uint8_t
222    readCounter(unsigned int num)
223    {
224        assert(num < 3);
225        return counter[num]->read();
226    }
227
228    void
229    writeCounter(unsigned int num, const uint8_t data)
230    {
231        assert(num < 3);
232        counter[num]->write(data);
233    }
234
235    bool
236    outputHigh(unsigned int num)
237    {
238        assert(num < 3);
239        return counter[num]->outputHigh();
240    }
241
242    unsigned int drain(Event *de);
243
244    /**
245     * Serialize this object to the given output stream.
246     * @param base The base name of the counter object.
247     * @param os The stream to serialize to.
248     */
249    void serialize(const std::string &base, std::ostream &os);
250
251    /**
252     * Reconstruct the state of this object from a checkpoint.
253     * @param base The base name of the counter object.
254     * @param cp The checkpoint use.
255     * @param section The section name of this object
256     */
257    void unserialize(const std::string &base, Checkpoint *cp,
258                     const std::string &section);
259};
260
261#endif // __DEV_8254_HH__
262