1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Andrew Schultz 30 * Miguel Serrano 31 */ 32 33/** @file 34 * Tsunami I/O including PIC, PIT, RTC, DMA 35 */ 36 37#include <sys/time.h> 38 39#include <deque> 40#include <string> 41#include <vector> 42
| 1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Andrew Schultz 30 * Miguel Serrano 31 */ 32 33/** @file 34 * Tsunami I/O including PIC, PIT, RTC, DMA 35 */ 36 37#include <sys/time.h> 38 39#include <deque> 40#include <string> 41#include <vector> 42
|
| 43#include "base/time.hh"
|
43#include "base/trace.hh" 44#include "dev/pitreg.h" 45#include "dev/rtcreg.h" 46#include "dev/alpha/tsunami_cchip.hh" 47#include "dev/alpha/tsunami.hh" 48#include "dev/alpha/tsunami_io.hh" 49#include "dev/alpha/tsunamireg.h" 50#include "mem/packet.hh" 51#include "mem/packet_access.hh" 52#include "mem/port.hh"
| 44#include "base/trace.hh" 45#include "dev/pitreg.h" 46#include "dev/rtcreg.h" 47#include "dev/alpha/tsunami_cchip.hh" 48#include "dev/alpha/tsunami.hh" 49#include "dev/alpha/tsunami_io.hh" 50#include "dev/alpha/tsunamireg.h" 51#include "mem/packet.hh" 52#include "mem/packet_access.hh" 53#include "mem/port.hh"
|
53#include "sim/builder.hh"
| |
54#include "sim/system.hh" 55 56using namespace std; 57//Should this be AlphaISA? 58using namespace TheISA; 59
| 54#include "sim/system.hh" 55 56using namespace std; 57//Should this be AlphaISA? 58using namespace TheISA; 59
|
60TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, const vector<int> &t, 61 bool bcd, Tick i) 62 : _name(n), event(tsunami, i), addr(0), year_is_bcd(bcd)
| 60TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, 61 const TsunamiIO::Params *p) 62 : _name(n), event(tsunami, p->frequency), addr(0)
|
63{ 64 memset(clock_data, 0, sizeof(clock_data)); 65 stat_regA = RTCA_32768HZ | RTCA_1024HZ; 66 stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 67
| 63{ 64 memset(clock_data, 0, sizeof(clock_data)); 65 stat_regA = RTCA_32768HZ | RTCA_1024HZ; 66 stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 67
|
68 struct tm tm; 69 parseTime(t, &tm);
| 68 year = p->time.tm_year;
|
70
| 69
|
71 year = tm.tm_year; 72 73 if (year_is_bcd) {
| 70 if (p->year_is_bcd) {
|
74 // The datasheet says that the year field can be either BCD or 75 // years since 1900. Linux seems to be happy with years since 76 // 1900. 77 year = year % 100; 78 int tens = year / 10; 79 int ones = year % 10; 80 year = (tens << 4) + ones; 81 } 82 83 // Unix is 0-11 for month, data seet says start at 1
| 71 // The datasheet says that the year field can be either BCD or 72 // years since 1900. Linux seems to be happy with years since 73 // 1900. 74 year = year % 100; 75 int tens = year / 10; 76 int ones = year % 10; 77 year = (tens << 4) + ones; 78 } 79 80 // Unix is 0-11 for month, data seet says start at 1
|
84 mon = tm.tm_mon + 1; 85 mday = tm.tm_mday; 86 hour = tm.tm_hour; 87 min = tm.tm_min; 88 sec = tm.tm_sec;
| 81 mon = p->time.tm_mon + 1; 82 mday = p->time.tm_mday; 83 hour = p->time.tm_hour; 84 min = p->time.tm_min; 85 sec = p->time.tm_sec;
|
89 90 // Datasheet says 1 is sunday
| 86 87 // Datasheet says 1 is sunday
|
91 wday = tm.tm_wday + 1;
| 88 wday = p->time.tm_wday + 1;
|
92
| 89
|
93 DPRINTFN("Real-time clock set to %s", asctime(&tm));
| 90 DPRINTFN("Real-time clock set to %s", asctime(&p->time));
|
94} 95 96void 97TsunamiIO::RTC::writeAddr(const uint8_t data) 98{ 99 if (data <= RTC_STAT_REGD) 100 addr = data; 101 else 102 panic("RTC addresses over 0xD are not implemented.\n"); 103} 104 105void 106TsunamiIO::RTC::writeData(const uint8_t data) 107{ 108 if (addr < RTC_STAT_REGA) 109 clock_data[addr] = data; 110 else { 111 switch (addr) { 112 case RTC_STAT_REGA: 113 if (data != (RTCA_32768HZ | RTCA_1024HZ)) 114 panic("Unimplemented RTC register A value write!\n"); 115 stat_regA = data; 116 break; 117 case RTC_STAT_REGB: 118 if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 119 panic("Write to RTC reg B bits that are not implemented!\n"); 120 121 if (data & RTCB_PRDC_IE) { 122 if (!event.scheduled()) 123 event.scheduleIntr(); 124 } else { 125 if (event.scheduled()) 126 event.deschedule(); 127 } 128 stat_regB = data; 129 break; 130 case RTC_STAT_REGC: 131 case RTC_STAT_REGD: 132 panic("RTC status registers C and D are not implemented.\n"); 133 break; 134 } 135 } 136} 137 138uint8_t 139TsunamiIO::RTC::readData() 140{ 141 if (addr < RTC_STAT_REGA) 142 return clock_data[addr]; 143 else { 144 switch (addr) { 145 case RTC_STAT_REGA: 146 // toggle UIP bit for linux 147 stat_regA ^= RTCA_UIP; 148 return stat_regA; 149 break; 150 case RTC_STAT_REGB: 151 return stat_regB; 152 break; 153 case RTC_STAT_REGC: 154 case RTC_STAT_REGD: 155 return 0x00; 156 break; 157 default: 158 panic("Shouldn't be here"); 159 } 160 } 161} 162 163void 164TsunamiIO::RTC::serialize(const string &base, ostream &os) 165{ 166 paramOut(os, base + ".addr", addr); 167 arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 168 paramOut(os, base + ".stat_regA", stat_regA); 169 paramOut(os, base + ".stat_regB", stat_regB); 170} 171 172void 173TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 174 const string §ion) 175{ 176 paramIn(cp, section, base + ".addr", addr); 177 arrayParamIn(cp, section, base + ".clock_data", clock_data, 178 sizeof(clock_data)); 179 paramIn(cp, section, base + ".stat_regA", stat_regA); 180 paramIn(cp, section, base + ".stat_regB", stat_regB); 181 182 // We're not unserializing the event here, but we need to 183 // rescehedule the event since curTick was moved forward by the 184 // checkpoint 185 event.reschedule(curTick + event.interval); 186} 187 188TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 189 : Event(&mainEventQueue), tsunami(t), interval(i) 190{ 191 DPRINTF(MC146818, "RTC Event Initilizing\n"); 192 schedule(curTick + interval); 193} 194 195void 196TsunamiIO::RTC::RTCEvent::scheduleIntr() 197{ 198 schedule(curTick + interval); 199} 200 201void 202TsunamiIO::RTC::RTCEvent::process() 203{ 204 DPRINTF(MC146818, "RTC Timer Interrupt\n"); 205 schedule(curTick + interval); 206 //Actually interrupt the processor here 207 tsunami->cchip->postRTC(); 208} 209 210const char * 211TsunamiIO::RTC::RTCEvent::description() 212{ 213 return "tsunami RTC interrupt"; 214} 215 216TsunamiIO::PITimer::PITimer(const string &name) 217 : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 218 counter2(name + ".counter2") 219{ 220 counter[0] = &counter0; 221 counter[1] = &counter0; 222 counter[2] = &counter0; 223} 224 225void 226TsunamiIO::PITimer::writeControl(const uint8_t data) 227{ 228 int rw; 229 int sel; 230 231 sel = GET_CTRL_SEL(data); 232 233 if (sel == PIT_READ_BACK) 234 panic("PITimer Read-Back Command is not implemented.\n"); 235 236 rw = GET_CTRL_RW(data); 237 238 if (rw == PIT_RW_LATCH_COMMAND) 239 counter[sel]->latchCount(); 240 else { 241 counter[sel]->setRW(rw); 242 counter[sel]->setMode(GET_CTRL_MODE(data)); 243 counter[sel]->setBCD(GET_CTRL_BCD(data)); 244 } 245} 246 247void 248TsunamiIO::PITimer::serialize(const string &base, ostream &os) 249{ 250 // serialize the counters 251 counter0.serialize(base + ".counter0", os); 252 counter1.serialize(base + ".counter1", os); 253 counter2.serialize(base + ".counter2", os); 254} 255 256void 257TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 258 const string §ion) 259{ 260 // unserialze the counters 261 counter0.unserialize(base + ".counter0", cp, section); 262 counter1.unserialize(base + ".counter1", cp, section); 263 counter2.unserialize(base + ".counter2", cp, section); 264} 265 266TsunamiIO::PITimer::Counter::Counter(const string &name) 267 : _name(name), event(this), count(0), latched_count(0), period(0), 268 mode(0), output_high(false), latch_on(false), read_byte(LSB), 269 write_byte(LSB) 270{ 271 272} 273 274void 275TsunamiIO::PITimer::Counter::latchCount() 276{ 277 // behave like a real latch 278 if(!latch_on) { 279 latch_on = true; 280 read_byte = LSB; 281 latched_count = count; 282 } 283} 284 285uint8_t 286TsunamiIO::PITimer::Counter::read() 287{ 288 if (latch_on) { 289 switch (read_byte) { 290 case LSB: 291 read_byte = MSB; 292 return (uint8_t)latched_count; 293 break; 294 case MSB: 295 read_byte = LSB; 296 latch_on = false; 297 return latched_count >> 8; 298 break; 299 default: 300 panic("Shouldn't be here"); 301 } 302 } else { 303 switch (read_byte) { 304 case LSB: 305 read_byte = MSB; 306 return (uint8_t)count; 307 break; 308 case MSB: 309 read_byte = LSB; 310 return count >> 8; 311 break; 312 default: 313 panic("Shouldn't be here"); 314 } 315 } 316} 317 318void 319TsunamiIO::PITimer::Counter::write(const uint8_t data) 320{ 321 switch (write_byte) { 322 case LSB: 323 count = (count & 0xFF00) | data; 324 325 if (event.scheduled()) 326 event.deschedule(); 327 output_high = false; 328 write_byte = MSB; 329 break; 330 331 case MSB: 332 count = (count & 0x00FF) | (data << 8); 333 period = count; 334 335 if (period > 0) { 336 DPRINTF(Tsunami, "Timer set to curTick + %d\n", 337 count * event.interval); 338 event.schedule(curTick + count * event.interval); 339 } 340 write_byte = LSB; 341 break; 342 } 343} 344 345void 346TsunamiIO::PITimer::Counter::setRW(int rw_val) 347{ 348 if (rw_val != PIT_RW_16BIT) 349 panic("Only LSB/MSB read/write is implemented.\n"); 350} 351 352void 353TsunamiIO::PITimer::Counter::setMode(int mode_val) 354{ 355 if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 356 mode_val != PIT_MODE_SQWAVE) 357 panic("PIT mode %#x is not implemented: \n", mode_val); 358 359 mode = mode_val; 360} 361 362void 363TsunamiIO::PITimer::Counter::setBCD(int bcd_val) 364{ 365 if (bcd_val != PIT_BCD_FALSE) 366 panic("PITimer does not implement BCD counts.\n"); 367} 368 369bool 370TsunamiIO::PITimer::Counter::outputHigh() 371{ 372 return output_high; 373} 374 375void 376TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 377{ 378 paramOut(os, base + ".count", count); 379 paramOut(os, base + ".latched_count", latched_count); 380 paramOut(os, base + ".period", period); 381 paramOut(os, base + ".mode", mode); 382 paramOut(os, base + ".output_high", output_high); 383 paramOut(os, base + ".latch_on", latch_on); 384 paramOut(os, base + ".read_byte", read_byte); 385 paramOut(os, base + ".write_byte", write_byte); 386 387 Tick event_tick = 0; 388 if (event.scheduled()) 389 event_tick = event.when(); 390 paramOut(os, base + ".event_tick", event_tick); 391} 392 393void 394TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 395 const string §ion) 396{ 397 paramIn(cp, section, base + ".count", count); 398 paramIn(cp, section, base + ".latched_count", latched_count); 399 paramIn(cp, section, base + ".period", period); 400 paramIn(cp, section, base + ".mode", mode); 401 paramIn(cp, section, base + ".output_high", output_high); 402 paramIn(cp, section, base + ".latch_on", latch_on); 403 paramIn(cp, section, base + ".read_byte", read_byte); 404 paramIn(cp, section, base + ".write_byte", write_byte); 405 406 Tick event_tick; 407 paramIn(cp, section, base + ".event_tick", event_tick); 408 if (event_tick) 409 event.schedule(event_tick); 410} 411 412TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 413 : Event(&mainEventQueue) 414{ 415 interval = (Tick)(Clock::Float::s / 1193180.0); 416 counter = c_ptr; 417} 418 419void 420TsunamiIO::PITimer::Counter::CounterEvent::process() 421{ 422 DPRINTF(Tsunami, "Timer Interrupt\n"); 423 switch (counter->mode) { 424 case PIT_MODE_INTTC: 425 counter->output_high = true; 426 case PIT_MODE_RATEGEN: 427 case PIT_MODE_SQWAVE: 428 break; 429 default: 430 panic("Unimplemented PITimer mode.\n"); 431 } 432} 433 434const char * 435TsunamiIO::PITimer::Counter::CounterEvent::description() 436{ 437 return "tsunami 8254 Interval timer"; 438} 439
| 91} 92 93void 94TsunamiIO::RTC::writeAddr(const uint8_t data) 95{ 96 if (data <= RTC_STAT_REGD) 97 addr = data; 98 else 99 panic("RTC addresses over 0xD are not implemented.\n"); 100} 101 102void 103TsunamiIO::RTC::writeData(const uint8_t data) 104{ 105 if (addr < RTC_STAT_REGA) 106 clock_data[addr] = data; 107 else { 108 switch (addr) { 109 case RTC_STAT_REGA: 110 if (data != (RTCA_32768HZ | RTCA_1024HZ)) 111 panic("Unimplemented RTC register A value write!\n"); 112 stat_regA = data; 113 break; 114 case RTC_STAT_REGB: 115 if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 116 panic("Write to RTC reg B bits that are not implemented!\n"); 117 118 if (data & RTCB_PRDC_IE) { 119 if (!event.scheduled()) 120 event.scheduleIntr(); 121 } else { 122 if (event.scheduled()) 123 event.deschedule(); 124 } 125 stat_regB = data; 126 break; 127 case RTC_STAT_REGC: 128 case RTC_STAT_REGD: 129 panic("RTC status registers C and D are not implemented.\n"); 130 break; 131 } 132 } 133} 134 135uint8_t 136TsunamiIO::RTC::readData() 137{ 138 if (addr < RTC_STAT_REGA) 139 return clock_data[addr]; 140 else { 141 switch (addr) { 142 case RTC_STAT_REGA: 143 // toggle UIP bit for linux 144 stat_regA ^= RTCA_UIP; 145 return stat_regA; 146 break; 147 case RTC_STAT_REGB: 148 return stat_regB; 149 break; 150 case RTC_STAT_REGC: 151 case RTC_STAT_REGD: 152 return 0x00; 153 break; 154 default: 155 panic("Shouldn't be here"); 156 } 157 } 158} 159 160void 161TsunamiIO::RTC::serialize(const string &base, ostream &os) 162{ 163 paramOut(os, base + ".addr", addr); 164 arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 165 paramOut(os, base + ".stat_regA", stat_regA); 166 paramOut(os, base + ".stat_regB", stat_regB); 167} 168 169void 170TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 171 const string §ion) 172{ 173 paramIn(cp, section, base + ".addr", addr); 174 arrayParamIn(cp, section, base + ".clock_data", clock_data, 175 sizeof(clock_data)); 176 paramIn(cp, section, base + ".stat_regA", stat_regA); 177 paramIn(cp, section, base + ".stat_regB", stat_regB); 178 179 // We're not unserializing the event here, but we need to 180 // rescehedule the event since curTick was moved forward by the 181 // checkpoint 182 event.reschedule(curTick + event.interval); 183} 184 185TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 186 : Event(&mainEventQueue), tsunami(t), interval(i) 187{ 188 DPRINTF(MC146818, "RTC Event Initilizing\n"); 189 schedule(curTick + interval); 190} 191 192void 193TsunamiIO::RTC::RTCEvent::scheduleIntr() 194{ 195 schedule(curTick + interval); 196} 197 198void 199TsunamiIO::RTC::RTCEvent::process() 200{ 201 DPRINTF(MC146818, "RTC Timer Interrupt\n"); 202 schedule(curTick + interval); 203 //Actually interrupt the processor here 204 tsunami->cchip->postRTC(); 205} 206 207const char * 208TsunamiIO::RTC::RTCEvent::description() 209{ 210 return "tsunami RTC interrupt"; 211} 212 213TsunamiIO::PITimer::PITimer(const string &name) 214 : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 215 counter2(name + ".counter2") 216{ 217 counter[0] = &counter0; 218 counter[1] = &counter0; 219 counter[2] = &counter0; 220} 221 222void 223TsunamiIO::PITimer::writeControl(const uint8_t data) 224{ 225 int rw; 226 int sel; 227 228 sel = GET_CTRL_SEL(data); 229 230 if (sel == PIT_READ_BACK) 231 panic("PITimer Read-Back Command is not implemented.\n"); 232 233 rw = GET_CTRL_RW(data); 234 235 if (rw == PIT_RW_LATCH_COMMAND) 236 counter[sel]->latchCount(); 237 else { 238 counter[sel]->setRW(rw); 239 counter[sel]->setMode(GET_CTRL_MODE(data)); 240 counter[sel]->setBCD(GET_CTRL_BCD(data)); 241 } 242} 243 244void 245TsunamiIO::PITimer::serialize(const string &base, ostream &os) 246{ 247 // serialize the counters 248 counter0.serialize(base + ".counter0", os); 249 counter1.serialize(base + ".counter1", os); 250 counter2.serialize(base + ".counter2", os); 251} 252 253void 254TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 255 const string §ion) 256{ 257 // unserialze the counters 258 counter0.unserialize(base + ".counter0", cp, section); 259 counter1.unserialize(base + ".counter1", cp, section); 260 counter2.unserialize(base + ".counter2", cp, section); 261} 262 263TsunamiIO::PITimer::Counter::Counter(const string &name) 264 : _name(name), event(this), count(0), latched_count(0), period(0), 265 mode(0), output_high(false), latch_on(false), read_byte(LSB), 266 write_byte(LSB) 267{ 268 269} 270 271void 272TsunamiIO::PITimer::Counter::latchCount() 273{ 274 // behave like a real latch 275 if(!latch_on) { 276 latch_on = true; 277 read_byte = LSB; 278 latched_count = count; 279 } 280} 281 282uint8_t 283TsunamiIO::PITimer::Counter::read() 284{ 285 if (latch_on) { 286 switch (read_byte) { 287 case LSB: 288 read_byte = MSB; 289 return (uint8_t)latched_count; 290 break; 291 case MSB: 292 read_byte = LSB; 293 latch_on = false; 294 return latched_count >> 8; 295 break; 296 default: 297 panic("Shouldn't be here"); 298 } 299 } else { 300 switch (read_byte) { 301 case LSB: 302 read_byte = MSB; 303 return (uint8_t)count; 304 break; 305 case MSB: 306 read_byte = LSB; 307 return count >> 8; 308 break; 309 default: 310 panic("Shouldn't be here"); 311 } 312 } 313} 314 315void 316TsunamiIO::PITimer::Counter::write(const uint8_t data) 317{ 318 switch (write_byte) { 319 case LSB: 320 count = (count & 0xFF00) | data; 321 322 if (event.scheduled()) 323 event.deschedule(); 324 output_high = false; 325 write_byte = MSB; 326 break; 327 328 case MSB: 329 count = (count & 0x00FF) | (data << 8); 330 period = count; 331 332 if (period > 0) { 333 DPRINTF(Tsunami, "Timer set to curTick + %d\n", 334 count * event.interval); 335 event.schedule(curTick + count * event.interval); 336 } 337 write_byte = LSB; 338 break; 339 } 340} 341 342void 343TsunamiIO::PITimer::Counter::setRW(int rw_val) 344{ 345 if (rw_val != PIT_RW_16BIT) 346 panic("Only LSB/MSB read/write is implemented.\n"); 347} 348 349void 350TsunamiIO::PITimer::Counter::setMode(int mode_val) 351{ 352 if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 353 mode_val != PIT_MODE_SQWAVE) 354 panic("PIT mode %#x is not implemented: \n", mode_val); 355 356 mode = mode_val; 357} 358 359void 360TsunamiIO::PITimer::Counter::setBCD(int bcd_val) 361{ 362 if (bcd_val != PIT_BCD_FALSE) 363 panic("PITimer does not implement BCD counts.\n"); 364} 365 366bool 367TsunamiIO::PITimer::Counter::outputHigh() 368{ 369 return output_high; 370} 371 372void 373TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 374{ 375 paramOut(os, base + ".count", count); 376 paramOut(os, base + ".latched_count", latched_count); 377 paramOut(os, base + ".period", period); 378 paramOut(os, base + ".mode", mode); 379 paramOut(os, base + ".output_high", output_high); 380 paramOut(os, base + ".latch_on", latch_on); 381 paramOut(os, base + ".read_byte", read_byte); 382 paramOut(os, base + ".write_byte", write_byte); 383 384 Tick event_tick = 0; 385 if (event.scheduled()) 386 event_tick = event.when(); 387 paramOut(os, base + ".event_tick", event_tick); 388} 389 390void 391TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 392 const string §ion) 393{ 394 paramIn(cp, section, base + ".count", count); 395 paramIn(cp, section, base + ".latched_count", latched_count); 396 paramIn(cp, section, base + ".period", period); 397 paramIn(cp, section, base + ".mode", mode); 398 paramIn(cp, section, base + ".output_high", output_high); 399 paramIn(cp, section, base + ".latch_on", latch_on); 400 paramIn(cp, section, base + ".read_byte", read_byte); 401 paramIn(cp, section, base + ".write_byte", write_byte); 402 403 Tick event_tick; 404 paramIn(cp, section, base + ".event_tick", event_tick); 405 if (event_tick) 406 event.schedule(event_tick); 407} 408 409TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 410 : Event(&mainEventQueue) 411{ 412 interval = (Tick)(Clock::Float::s / 1193180.0); 413 counter = c_ptr; 414} 415 416void 417TsunamiIO::PITimer::Counter::CounterEvent::process() 418{ 419 DPRINTF(Tsunami, "Timer Interrupt\n"); 420 switch (counter->mode) { 421 case PIT_MODE_INTTC: 422 counter->output_high = true; 423 case PIT_MODE_RATEGEN: 424 case PIT_MODE_SQWAVE: 425 break; 426 default: 427 panic("Unimplemented PITimer mode.\n"); 428 } 429} 430 431const char * 432TsunamiIO::PITimer::Counter::CounterEvent::description() 433{ 434 return "tsunami 8254 Interval timer"; 435} 436
|
440TsunamiIO::TsunamiIO(Params *p)
| 437TsunamiIO::TsunamiIO(const Params *p)
|
441 : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
| 438 : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
442 rtc(p->name + ".rtc", p->tsunami, p->init_time, p->year_is_bcd, 443 p->frequency)
| 439 rtc(p->name + ".rtc", p->tsunami, p)
|
444{ 445 pioSize = 0x100; 446 447 // set the back pointer from tsunami to myself 448 tsunami->io = this; 449 450 timerData = 0; 451 picr = 0; 452 picInterrupting = false; 453} 454 455Tick 456TsunamiIO::frequency() const 457{ 458 return Clock::Frequency / params()->frequency; 459} 460 461Tick 462TsunamiIO::read(PacketPtr pkt) 463{ 464 assert(pkt->result == Packet::Unknown); 465 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 466 467 Addr daddr = pkt->getAddr() - pioAddr; 468 469 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 470 pkt->getSize(), daddr); 471 472 pkt->allocate(); 473 474 if (pkt->getSize() == sizeof(uint8_t)) { 475 switch(daddr) { 476 // PIC1 mask read 477 case TSDEV_PIC1_MASK: 478 pkt->set(~mask1); 479 break; 480 case TSDEV_PIC2_MASK: 481 pkt->set(~mask2); 482 break; 483 case TSDEV_PIC1_ISR: 484 // !!! If this is modified 64bit case needs to be too 485 // Pal code has to do a 64 bit physical read because there is 486 // no load physical byte instruction 487 pkt->set(picr); 488 break; 489 case TSDEV_PIC2_ISR: 490 // PIC2 not implemnted... just return 0 491 pkt->set(0x00); 492 break; 493 case TSDEV_TMR0_DATA: 494 pkt->set(pitimer.counter0.read()); 495 break; 496 case TSDEV_TMR1_DATA: 497 pkt->set(pitimer.counter1.read()); 498 break; 499 case TSDEV_TMR2_DATA: 500 pkt->set(pitimer.counter2.read()); 501 break; 502 case TSDEV_RTC_DATA: 503 pkt->set(rtc.readData()); 504 break; 505 case TSDEV_CTRL_PORTB: 506 if (pitimer.counter2.outputHigh()) 507 pkt->set(PORTB_SPKR_HIGH); 508 else 509 pkt->set(0x00); 510 break; 511 default: 512 panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 513 } 514 } else if (pkt->getSize() == sizeof(uint64_t)) { 515 if (daddr == TSDEV_PIC1_ISR) 516 pkt->set<uint64_t>(picr); 517 else 518 panic("I/O Read - invalid addr - va %#x size %d\n", 519 pkt->getAddr(), pkt->getSize()); 520 } else { 521 panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 522 } 523 pkt->result = Packet::Success; 524 return pioDelay; 525} 526 527Tick 528TsunamiIO::write(PacketPtr pkt) 529{ 530 assert(pkt->result == Packet::Unknown); 531 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 532 Addr daddr = pkt->getAddr() - pioAddr; 533 534 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 535 pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 536 537 assert(pkt->getSize() == sizeof(uint8_t)); 538 539 switch(daddr) { 540 case TSDEV_PIC1_MASK: 541 mask1 = ~(pkt->get<uint8_t>()); 542 if ((picr & mask1) && !picInterrupting) { 543 picInterrupting = true; 544 tsunami->cchip->postDRIR(55); 545 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 546 } 547 if ((!(picr & mask1)) && picInterrupting) { 548 picInterrupting = false; 549 tsunami->cchip->clearDRIR(55); 550 DPRINTF(Tsunami, "clearing pic interrupt\n"); 551 } 552 break; 553 case TSDEV_PIC2_MASK: 554 mask2 = pkt->get<uint8_t>(); 555 //PIC2 Not implemented to interrupt 556 break; 557 case TSDEV_PIC1_ACK: 558 // clear the interrupt on the PIC 559 picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 560 if (!(picr & mask1)) 561 tsunami->cchip->clearDRIR(55); 562 break; 563 case TSDEV_DMA1_MODE: 564 mode1 = pkt->get<uint8_t>(); 565 break; 566 case TSDEV_DMA2_MODE: 567 mode2 = pkt->get<uint8_t>(); 568 break; 569 case TSDEV_TMR0_DATA: 570 pitimer.counter0.write(pkt->get<uint8_t>()); 571 break; 572 case TSDEV_TMR1_DATA: 573 pitimer.counter1.write(pkt->get<uint8_t>()); 574 break; 575 case TSDEV_TMR2_DATA: 576 pitimer.counter2.write(pkt->get<uint8_t>()); 577 break; 578 case TSDEV_TMR_CTRL: 579 pitimer.writeControl(pkt->get<uint8_t>()); 580 break; 581 case TSDEV_RTC_ADDR: 582 rtc.writeAddr(pkt->get<uint8_t>()); 583 break; 584 case TSDEV_RTC_DATA: 585 rtc.writeData(pkt->get<uint8_t>()); 586 break; 587 case TSDEV_KBD: 588 case TSDEV_DMA1_CMND: 589 case TSDEV_DMA2_CMND: 590 case TSDEV_DMA1_MMASK: 591 case TSDEV_DMA2_MMASK: 592 case TSDEV_PIC2_ACK: 593 case TSDEV_DMA1_RESET: 594 case TSDEV_DMA2_RESET: 595 case TSDEV_DMA1_MASK: 596 case TSDEV_DMA2_MASK: 597 case TSDEV_CTRL_PORTB: 598 break; 599 default: 600 panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 601 } 602 603 pkt->result = Packet::Success; 604 return pioDelay; 605} 606 607void 608TsunamiIO::postPIC(uint8_t bitvector) 609{ 610 //PIC2 Is not implemented, because nothing of interest there 611 picr |= bitvector; 612 if (picr & mask1) { 613 tsunami->cchip->postDRIR(55); 614 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 615 } 616} 617 618void 619TsunamiIO::clearPIC(uint8_t bitvector) 620{ 621 //PIC2 Is not implemented, because nothing of interest there 622 picr &= ~bitvector; 623 if (!(picr & mask1)) { 624 tsunami->cchip->clearDRIR(55); 625 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 626 } 627} 628 629void 630TsunamiIO::serialize(ostream &os) 631{ 632 SERIALIZE_SCALAR(timerData); 633 SERIALIZE_SCALAR(mask1); 634 SERIALIZE_SCALAR(mask2); 635 SERIALIZE_SCALAR(mode1); 636 SERIALIZE_SCALAR(mode2); 637 SERIALIZE_SCALAR(picr); 638 SERIALIZE_SCALAR(picInterrupting); 639 640 // Serialize the timers 641 pitimer.serialize("pitimer", os); 642 rtc.serialize("rtc", os); 643} 644 645void 646TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 647{ 648 UNSERIALIZE_SCALAR(timerData); 649 UNSERIALIZE_SCALAR(mask1); 650 UNSERIALIZE_SCALAR(mask2); 651 UNSERIALIZE_SCALAR(mode1); 652 UNSERIALIZE_SCALAR(mode2); 653 UNSERIALIZE_SCALAR(picr); 654 UNSERIALIZE_SCALAR(picInterrupting); 655 656 // Unserialize the timers 657 pitimer.unserialize("pitimer", cp, section); 658 rtc.unserialize("rtc", cp, section); 659} 660
| 440{ 441 pioSize = 0x100; 442 443 // set the back pointer from tsunami to myself 444 tsunami->io = this; 445 446 timerData = 0; 447 picr = 0; 448 picInterrupting = false; 449} 450 451Tick 452TsunamiIO::frequency() const 453{ 454 return Clock::Frequency / params()->frequency; 455} 456 457Tick 458TsunamiIO::read(PacketPtr pkt) 459{ 460 assert(pkt->result == Packet::Unknown); 461 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 462 463 Addr daddr = pkt->getAddr() - pioAddr; 464 465 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 466 pkt->getSize(), daddr); 467 468 pkt->allocate(); 469 470 if (pkt->getSize() == sizeof(uint8_t)) { 471 switch(daddr) { 472 // PIC1 mask read 473 case TSDEV_PIC1_MASK: 474 pkt->set(~mask1); 475 break; 476 case TSDEV_PIC2_MASK: 477 pkt->set(~mask2); 478 break; 479 case TSDEV_PIC1_ISR: 480 // !!! If this is modified 64bit case needs to be too 481 // Pal code has to do a 64 bit physical read because there is 482 // no load physical byte instruction 483 pkt->set(picr); 484 break; 485 case TSDEV_PIC2_ISR: 486 // PIC2 not implemnted... just return 0 487 pkt->set(0x00); 488 break; 489 case TSDEV_TMR0_DATA: 490 pkt->set(pitimer.counter0.read()); 491 break; 492 case TSDEV_TMR1_DATA: 493 pkt->set(pitimer.counter1.read()); 494 break; 495 case TSDEV_TMR2_DATA: 496 pkt->set(pitimer.counter2.read()); 497 break; 498 case TSDEV_RTC_DATA: 499 pkt->set(rtc.readData()); 500 break; 501 case TSDEV_CTRL_PORTB: 502 if (pitimer.counter2.outputHigh()) 503 pkt->set(PORTB_SPKR_HIGH); 504 else 505 pkt->set(0x00); 506 break; 507 default: 508 panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 509 } 510 } else if (pkt->getSize() == sizeof(uint64_t)) { 511 if (daddr == TSDEV_PIC1_ISR) 512 pkt->set<uint64_t>(picr); 513 else 514 panic("I/O Read - invalid addr - va %#x size %d\n", 515 pkt->getAddr(), pkt->getSize()); 516 } else { 517 panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 518 } 519 pkt->result = Packet::Success; 520 return pioDelay; 521} 522 523Tick 524TsunamiIO::write(PacketPtr pkt) 525{ 526 assert(pkt->result == Packet::Unknown); 527 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 528 Addr daddr = pkt->getAddr() - pioAddr; 529 530 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 531 pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 532 533 assert(pkt->getSize() == sizeof(uint8_t)); 534 535 switch(daddr) { 536 case TSDEV_PIC1_MASK: 537 mask1 = ~(pkt->get<uint8_t>()); 538 if ((picr & mask1) && !picInterrupting) { 539 picInterrupting = true; 540 tsunami->cchip->postDRIR(55); 541 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 542 } 543 if ((!(picr & mask1)) && picInterrupting) { 544 picInterrupting = false; 545 tsunami->cchip->clearDRIR(55); 546 DPRINTF(Tsunami, "clearing pic interrupt\n"); 547 } 548 break; 549 case TSDEV_PIC2_MASK: 550 mask2 = pkt->get<uint8_t>(); 551 //PIC2 Not implemented to interrupt 552 break; 553 case TSDEV_PIC1_ACK: 554 // clear the interrupt on the PIC 555 picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 556 if (!(picr & mask1)) 557 tsunami->cchip->clearDRIR(55); 558 break; 559 case TSDEV_DMA1_MODE: 560 mode1 = pkt->get<uint8_t>(); 561 break; 562 case TSDEV_DMA2_MODE: 563 mode2 = pkt->get<uint8_t>(); 564 break; 565 case TSDEV_TMR0_DATA: 566 pitimer.counter0.write(pkt->get<uint8_t>()); 567 break; 568 case TSDEV_TMR1_DATA: 569 pitimer.counter1.write(pkt->get<uint8_t>()); 570 break; 571 case TSDEV_TMR2_DATA: 572 pitimer.counter2.write(pkt->get<uint8_t>()); 573 break; 574 case TSDEV_TMR_CTRL: 575 pitimer.writeControl(pkt->get<uint8_t>()); 576 break; 577 case TSDEV_RTC_ADDR: 578 rtc.writeAddr(pkt->get<uint8_t>()); 579 break; 580 case TSDEV_RTC_DATA: 581 rtc.writeData(pkt->get<uint8_t>()); 582 break; 583 case TSDEV_KBD: 584 case TSDEV_DMA1_CMND: 585 case TSDEV_DMA2_CMND: 586 case TSDEV_DMA1_MMASK: 587 case TSDEV_DMA2_MMASK: 588 case TSDEV_PIC2_ACK: 589 case TSDEV_DMA1_RESET: 590 case TSDEV_DMA2_RESET: 591 case TSDEV_DMA1_MASK: 592 case TSDEV_DMA2_MASK: 593 case TSDEV_CTRL_PORTB: 594 break; 595 default: 596 panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 597 } 598 599 pkt->result = Packet::Success; 600 return pioDelay; 601} 602 603void 604TsunamiIO::postPIC(uint8_t bitvector) 605{ 606 //PIC2 Is not implemented, because nothing of interest there 607 picr |= bitvector; 608 if (picr & mask1) { 609 tsunami->cchip->postDRIR(55); 610 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 611 } 612} 613 614void 615TsunamiIO::clearPIC(uint8_t bitvector) 616{ 617 //PIC2 Is not implemented, because nothing of interest there 618 picr &= ~bitvector; 619 if (!(picr & mask1)) { 620 tsunami->cchip->clearDRIR(55); 621 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 622 } 623} 624 625void 626TsunamiIO::serialize(ostream &os) 627{ 628 SERIALIZE_SCALAR(timerData); 629 SERIALIZE_SCALAR(mask1); 630 SERIALIZE_SCALAR(mask2); 631 SERIALIZE_SCALAR(mode1); 632 SERIALIZE_SCALAR(mode2); 633 SERIALIZE_SCALAR(picr); 634 SERIALIZE_SCALAR(picInterrupting); 635 636 // Serialize the timers 637 pitimer.serialize("pitimer", os); 638 rtc.serialize("rtc", os); 639} 640 641void 642TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 643{ 644 UNSERIALIZE_SCALAR(timerData); 645 UNSERIALIZE_SCALAR(mask1); 646 UNSERIALIZE_SCALAR(mask2); 647 UNSERIALIZE_SCALAR(mode1); 648 UNSERIALIZE_SCALAR(mode2); 649 UNSERIALIZE_SCALAR(picr); 650 UNSERIALIZE_SCALAR(picInterrupting); 651 652 // Unserialize the timers 653 pitimer.unserialize("pitimer", cp, section); 654 rtc.unserialize("rtc", cp, section); 655} 656
|
661BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 662 663 Param<Addr> pio_addr; 664 Param<Tick> pio_latency; 665 Param<Tick> frequency; 666 SimObjectParam<Platform *> platform; 667 SimObjectParam<System *> system; 668 VectorParam<int> time; 669 Param<bool> year_is_bcd; 670 SimObjectParam<Tsunami *> tsunami; 671 672END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 673 674BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 675 676 INIT_PARAM(pio_addr, "Device Address"), 677 INIT_PARAM(pio_latency, "Programmed IO latency"), 678 INIT_PARAM(frequency, "clock interrupt frequency"), 679 INIT_PARAM(platform, "platform"), 680 INIT_PARAM(system, "system object"), 681 INIT_PARAM(time, "System time to use (0 for actual time"), 682 INIT_PARAM(year_is_bcd, ""), 683 INIT_PARAM(tsunami, "Tsunami") 684 685END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 686 687CREATE_SIM_OBJECT(TsunamiIO)
| 657TsunamiIO * 658TsunamiIOParams::create()
|
688{
| 659{
|
689 TsunamiIO::Params *p = new TsunamiIO::Params; 690 p->frequency = frequency; 691 p->name = getInstanceName(); 692 p->pio_addr = pio_addr; 693 p->pio_delay = pio_latency; 694 p->platform = platform; 695 p->system = system; 696 p->init_time = time; 697 p->year_is_bcd = year_is_bcd; 698 p->tsunami = tsunami; 699 return new TsunamiIO(p);
| 660 return new TsunamiIO(this);
|
700}
| 661}
|
701 702REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
| |
| |