intel_8254_timer.hh revision 10642
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 <iostream>
37#include <string>
38
39#include "base/bitunion.hh"
40#include "base/types.hh"
41#include "base/trace.hh"
42#include "debug/Intel8254Timer.hh"
43#include "sim/eventq_impl.hh"
44#include "sim/serialize.hh"
45
46/** Programmable Interval Timer (Intel 8254) */
47class Intel8254Timer : public EventManager
48{
49  protected:
50    BitUnion8(CtrlReg)
51        Bitfield<7, 6> sel;
52        Bitfield<5, 4> rw;
53        Bitfield<3, 1> mode;
54        Bitfield<0> bcd;
55    EndBitUnion(CtrlReg)
56
57    enum SelectVal {
58        SelectCounter0,
59        SelectCounter1,
60        SelectCounter2,
61        ReadBackCommand
62    };
63
64    enum ReadWriteVal {
65        LatchCommand,
66        LsbOnly,
67        MsbOnly,
68        TwoPhase
69    };
70
71    enum ModeVal {
72        InitTc,
73        OneShot,
74        RateGen,
75        SquareWave,
76        SoftwareStrobe,
77        HardwareStrobe
78    };
79
80    /** Counter element for PIT */
81    class Counter
82    {
83        /** Event for counter interrupt */
84        class CounterEvent : public Event
85        {
86          private:
87            /** Pointer back to Counter */
88            Counter* counter;
89            Tick interval;
90
91          public:
92            CounterEvent(Counter*);
93
94            /** Event process */
95            void process();
96
97            /** Event description */
98            virtual const char *description() const;
99
100            friend class Counter;
101
102            void setTo(int clocks);
103
104            int clocksLeft();
105
106            Tick getInterval();
107        };
108
109      private:
110        std::string _name;
111        const std::string &name() const { return _name; }
112
113        unsigned int num;
114
115        CounterEvent event;
116
117        /** True after startup is called. */
118        bool running;
119
120        /** Initial count value */
121        uint16_t initial_count;
122
123        /** Latched count */
124        uint16_t latched_count;
125
126        /** Interrupt period */
127        uint16_t period;
128
129        /** When to start ticking */
130        Tick offset;
131
132        /** Current mode of operation */
133        uint8_t mode;
134
135        /** Output goes high when the counter reaches zero */
136        bool output_high;
137
138        /** State of the count latch */
139        bool latch_on;
140
141        /** Set of values for read_byte and write_byte */
142        enum {LSB, MSB};
143
144        /** Determine which byte of a 16-bit count value to read/write */
145        uint8_t read_byte, write_byte;
146
147        /** Pointer to container */
148        Intel8254Timer *parent;
149
150      public:
151        Counter(Intel8254Timer *p, const std::string &name, unsigned int num);
152
153        /** Latch the current count (if one is not already latched) */
154        void latchCount();
155
156        /** Get the current count for this counter */
157        int currentCount();
158
159        /** Set the read/write mode */
160        void setRW(int rw_val);
161
162        /** Set operational mode */
163        void setMode(int mode_val);
164
165        /** Set count encoding */
166        void setBCD(int bcd_val);
167
168        /** Read a count byte */
169        uint8_t read();
170
171        /** Write a count byte */
172        void write(const uint8_t data);
173
174        /** Is the output high? */
175        bool outputHigh();
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        /** Start ticking */
194        void startup();
195    };
196
197  protected:
198    std::string _name;
199    const std::string &name() const { return _name; }
200
201    /** PIT has three seperate counters */
202    Counter *counter[3];
203
204    virtual void
205    counterInterrupt(unsigned int num)
206    {
207        DPRINTF(Intel8254Timer, "Timer interrupt from counter %d.\n", num);
208    }
209
210  public:
211
212    virtual
213    ~Intel8254Timer()
214    {}
215
216    Intel8254Timer(EventManager *em, const std::string &name,
217            Counter *counter0, Counter *counter1, Counter *counter2);
218
219    Intel8254Timer(EventManager *em, const std::string &name);
220
221    /** Write control word */
222    void writeControl(const CtrlReg data);
223
224    uint8_t
225    readCounter(unsigned int num)
226    {
227        assert(num < 3);
228        return counter[num]->read();
229    }
230
231    void
232    writeCounter(unsigned int num, const uint8_t data)
233    {
234        assert(num < 3);
235        counter[num]->write(data);
236    }
237
238    bool
239    outputHigh(unsigned int num)
240    {
241        assert(num < 3);
242        return counter[num]->outputHigh();
243    }
244
245    /**
246     * Serialize this object to the given output stream.
247     * @param base The base name of the counter object.
248     * @param os The stream to serialize to.
249     */
250    void serialize(const std::string &base, std::ostream &os);
251
252    /**
253     * Reconstruct the state of this object from a checkpoint.
254     * @param base The base name of the counter object.
255     * @param cp The checkpoint use.
256     * @param section The section name of this object
257     */
258    void unserialize(const std::string &base, Checkpoint *cp,
259                     const std::string &section);
260
261    /** Start ticking */
262    void startup();
263};
264
265#endif // __DEV_8254_HH__
266