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 --- 76 unchanged lines hidden (view full) --- 85 // unserialze the counters 86 counter[0]->unserialize(base + ".counter0", cp, section); 87 counter[1]->unserialize(base + ".counter1", cp, section); 88 counter[2]->unserialize(base + ".counter2", cp, section); 89} 90 91Intel8254Timer::Counter::Counter(Intel8254Timer *p, 92 const string &name, unsigned int _num) |
93 : _name(name), num(_num), event(this), initial_count(0), |
94 latched_count(0), period(0), mode(0), output_high(false), 95 latch_on(false), read_byte(LSB), write_byte(LSB), parent(p) 96{ 97 98} 99 100void 101Intel8254Timer::Counter::latchCount() 102{ 103 // behave like a real latch 104 if(!latch_on) { 105 latch_on = true; 106 read_byte = LSB; |
107 latched_count = currentCount(); |
108 } 109} 110 |
111int 112Intel8254Timer::Counter::currentCount() 113{ 114 int clocks = event.clocksLeft(); 115 if (clocks == -1) { 116 warn_once("Reading current count from inactive timer.\n"); 117 return 0; 118 } 119 if (mode == RateGen || mode == SquareWave) 120 return clocks + 1; 121 else 122 return clocks; 123} 124 |
125uint8_t 126Intel8254Timer::Counter::read() 127{ 128 if (latch_on) { 129 switch (read_byte) { 130 case LSB: 131 read_byte = MSB; 132 return (uint8_t)latched_count; 133 break; 134 case MSB: 135 read_byte = LSB; 136 latch_on = false; 137 return latched_count >> 8; 138 break; 139 default: 140 panic("Shouldn't be here"); 141 } 142 } else { |
143 uint16_t count = currentCount(); |
144 switch (read_byte) { 145 case LSB: 146 read_byte = MSB; 147 return (uint8_t)count; 148 break; 149 case MSB: 150 read_byte = LSB; 151 return count >> 8; --- 4 unchanged lines hidden (view full) --- 156 } 157} 158 159void 160Intel8254Timer::Counter::write(const uint8_t data) 161{ 162 switch (write_byte) { 163 case LSB: |
164 initial_count = (initial_count & 0xFF00) | data; |
165 166 if (event.scheduled()) 167 parent->deschedule(event); 168 output_high = false; 169 write_byte = MSB; 170 break; 171 172 case MSB: |
173 initial_count = (initial_count & 0x00FF) | (data << 8); |
174 // In the RateGen or SquareWave modes, the timer wraps around and 175 // triggers on a value of 1, not 0. 176 if (mode == RateGen || mode == SquareWave) |
177 period = initial_count - 1; |
178 else |
179 period = initial_count; |
180 181 if (period > 0) 182 event.setTo(period); 183 184 write_byte = LSB; 185 break; 186 } 187} --- 26 unchanged lines hidden (view full) --- 214Intel8254Timer::Counter::outputHigh() 215{ 216 return output_high; 217} 218 219void 220Intel8254Timer::Counter::serialize(const string &base, ostream &os) 221{ |
222 paramOut(os, base + ".initial_count", initial_count); |
223 paramOut(os, base + ".latched_count", latched_count); 224 paramOut(os, base + ".period", period); 225 paramOut(os, base + ".mode", mode); 226 paramOut(os, base + ".output_high", output_high); 227 paramOut(os, base + ".latch_on", latch_on); 228 paramOut(os, base + ".read_byte", read_byte); 229 paramOut(os, base + ".write_byte", write_byte); 230 231 Tick event_tick = 0; 232 if (event.scheduled()) 233 event_tick = event.when(); 234 paramOut(os, base + ".event_tick", event_tick); 235} 236 237void 238Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp, 239 const string §ion) 240{ |
241 paramIn(cp, section, base + ".initial_count", initial_count); |
242 paramIn(cp, section, base + ".latched_count", latched_count); 243 paramIn(cp, section, base + ".period", period); 244 paramIn(cp, section, base + ".mode", mode); 245 paramIn(cp, section, base + ".output_high", output_high); 246 paramIn(cp, section, base + ".latch_on", latch_on); 247 paramIn(cp, section, base + ".read_byte", read_byte); 248 paramIn(cp, section, base + ".write_byte", write_byte); 249 --- 31 unchanged lines hidden (view full) --- 281{ 282 if (clocks == 0) 283 panic("Timer can't be set to go off instantly.\n"); 284 DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n", 285 clocks * interval); 286 counter->parent->schedule(this, curTick + clocks * interval); 287} 288 |
289int 290Intel8254Timer::Counter::CounterEvent::clocksLeft() 291{ 292 if (!scheduled()) 293 return -1; 294 return (when() - curTick + interval - 1) / interval; 295} 296 |
297const char * 298Intel8254Timer::Counter::CounterEvent::description() const 299{ 300 return "Intel 8254 Interval timer"; 301} |