sinic.cc revision 1939
13005Sstever@eecs.umich.edu/* 23005Sstever@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 33005Sstever@eecs.umich.edu * All rights reserved. 43005Sstever@eecs.umich.edu * 53005Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 63005Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 73005Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 83005Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 93005Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 103005Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 113005Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 123005Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 133005Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 143005Sstever@eecs.umich.edu * this software without specific prior written permission. 153005Sstever@eecs.umich.edu * 163005Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173005Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183005Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193005Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203005Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213005Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223005Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233005Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243005Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253005Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263005Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273005Sstever@eecs.umich.edu */ 283005Sstever@eecs.umich.edu 292889SN/A#include <cstdio> 302889SN/A#include <deque> 312710SN/A#include <string> 322710SN/A 332934SN/A#include "base/inet.hh" 342934SN/A#include "cpu/exec_context.hh" 352549SN/A#include "cpu/intr_control.hh" 362995SN/A#include "dev/etherlink.hh" 373395Shsul@eecs.umich.edu#include "dev/sinic.hh" 382549SN/A#include "dev/pciconfigall.hh" 393088Sstever@eecs.umich.edu#include "mem/bus/bus.hh" 403088Sstever@eecs.umich.edu#include "mem/bus/dma_interface.hh" 413088Sstever@eecs.umich.edu#include "mem/bus/pio_interface.hh" 423444Sktlim@umich.edu#include "mem/bus/pio_interface_impl.hh" 433444Sktlim@umich.edu#include "mem/functional/memory_control.hh" 443444Sktlim@umich.edu#include "mem/functional/physical.hh" 453444Sktlim@umich.edu#include "sim/builder.hh" 462889SN/A#include "sim/debug.hh" 472710SN/A#include "sim/eventq.hh" 483322Shsul@eecs.umich.edu#include "sim/host.hh" 492995SN/A#include "sim/stats.hh" 502995SN/A#include "targetarch/vtophys.hh" 512995SN/A 522995SN/Ausing namespace Net; 532995SN/A 543143Shsul@eecs.umich.edunamespace Sinic { 553322Shsul@eecs.umich.edu 563322Shsul@eecs.umich.educonst char *RxStateStrings[] = 573025Ssaidi@eecs.umich.edu{ 583143Shsul@eecs.umich.edu "rxIdle", 593143Shsul@eecs.umich.edu "rxFifoBlock", 603322Shsul@eecs.umich.edu "rxBeginCopy", 613444Sktlim@umich.edu "rxCopy", 623322Shsul@eecs.umich.edu "rxCopyDone" 632710SN/A}; 642710SN/A 652710SN/Aconst char *TxStateStrings[] = 662710SN/A{ 672710SN/A "txIdle", 682710SN/A "txFifoBlock", 693322Shsul@eecs.umich.edu "txBeginCopy", 703304Sstever@eecs.umich.edu "txCopy", 713322Shsul@eecs.umich.edu "txCopyDone" 723322Shsul@eecs.umich.edu}; 733304Sstever@eecs.umich.edu 743322Shsul@eecs.umich.edu 752934SN/A/////////////////////////////////////////////////////////////////////// 763322Shsul@eecs.umich.edu// 773322Shsul@eecs.umich.edu// Sinic PCI Device 782934SN/A// 793322Shsul@eecs.umich.eduBase::Base(Params *p) 803322Shsul@eecs.umich.edu : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock), 812934SN/A intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false), 823322Shsul@eecs.umich.edu cpuPendingIntr(false), intrEvent(0), interface(NULL) 833322Shsul@eecs.umich.edu{ 842566SN/A} 853322Shsul@eecs.umich.edu 863322Shsul@eecs.umich.eduDevice::Device(Params *p) 872995SN/A : Base(p), plat(p->plat), physmem(p->physmem), 882995SN/A rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), 893304Sstever@eecs.umich.edu rxKickTick(0), txKickTick(0), 903304Sstever@eecs.umich.edu txEvent(this), rxDmaEvent(this), txDmaEvent(this), 913304Sstever@eecs.umich.edu dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), 922995SN/A dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor) 932995SN/A{ 942995SN/A reset(); 952917SN/A 962995SN/A if (p->io_bus) { 973304Sstever@eecs.umich.edu pioInterface = newPioInterface(p->name + ".pio", p->hier, p->io_bus, 982995SN/A this, &Device::cacheAccess); 993304Sstever@eecs.umich.edu 1003304Sstever@eecs.umich.edu pioLatency = p->pio_latency * p->io_bus->clockRate; 1013322Shsul@eecs.umich.edu 1023312Sstever@eecs.umich.edu if (p->payload_bus) 1033322Shsul@eecs.umich.edu dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->io_bus, 1043312Sstever@eecs.umich.edu p->payload_bus, 1, 1053322Shsul@eecs.umich.edu p->dma_no_allocate); 1063395Shsul@eecs.umich.edu else 1073395Shsul@eecs.umich.edu dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->io_bus, 1083322Shsul@eecs.umich.edu p->io_bus, 1, 1093322Shsul@eecs.umich.edu p->dma_no_allocate); 1103005Sstever@eecs.umich.edu } else if (p->payload_bus) { 1113005Sstever@eecs.umich.edu pioInterface = newPioInterface(p->name + ".pio", p->hier, 1123322Shsul@eecs.umich.edu p->payload_bus, this, 1133322Shsul@eecs.umich.edu &Device::cacheAccess); 1143322Shsul@eecs.umich.edu 1153322Shsul@eecs.umich.edu pioLatency = p->pio_latency * p->payload_bus->clockRate; 1163322Shsul@eecs.umich.edu 1173005Sstever@eecs.umich.edu dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus, 1183322Shsul@eecs.umich.edu p->payload_bus, 1, 1193005Sstever@eecs.umich.edu p->dma_no_allocate); 1203005Sstever@eecs.umich.edu } 1213005Sstever@eecs.umich.edu} 1222566SN/A 1233395Shsul@eecs.umich.eduDevice::~Device() 124{} 125 126void 127Device::regStats() 128{ 129 rxBytes 130 .name(name() + ".rxBytes") 131 .desc("Bytes Received") 132 .prereq(rxBytes) 133 ; 134 135 rxBandwidth 136 .name(name() + ".rxBandwidth") 137 .desc("Receive Bandwidth (bits/s)") 138 .precision(0) 139 .prereq(rxBytes) 140 ; 141 142 rxPackets 143 .name(name() + ".rxPackets") 144 .desc("Number of Packets Received") 145 .prereq(rxBytes) 146 ; 147 148 rxPacketRate 149 .name(name() + ".rxPPS") 150 .desc("Packet Reception Rate (packets/s)") 151 .precision(0) 152 .prereq(rxBytes) 153 ; 154 155 rxIpPackets 156 .name(name() + ".rxIpPackets") 157 .desc("Number of IP Packets Received") 158 .prereq(rxBytes) 159 ; 160 161 rxTcpPackets 162 .name(name() + ".rxTcpPackets") 163 .desc("Number of Packets Received") 164 .prereq(rxBytes) 165 ; 166 167 rxUdpPackets 168 .name(name() + ".rxUdpPackets") 169 .desc("Number of UDP Packets Received") 170 .prereq(rxBytes) 171 ; 172 173 rxIpChecksums 174 .name(name() + ".rxIpChecksums") 175 .desc("Number of rx IP Checksums done by device") 176 .precision(0) 177 .prereq(rxBytes) 178 ; 179 180 rxTcpChecksums 181 .name(name() + ".rxTcpChecksums") 182 .desc("Number of rx TCP Checksums done by device") 183 .precision(0) 184 .prereq(rxBytes) 185 ; 186 187 rxUdpChecksums 188 .name(name() + ".rxUdpChecksums") 189 .desc("Number of rx UDP Checksums done by device") 190 .precision(0) 191 .prereq(rxBytes) 192 ; 193 194 totBandwidth 195 .name(name() + ".totBandwidth") 196 .desc("Total Bandwidth (bits/s)") 197 .precision(0) 198 .prereq(totBytes) 199 ; 200 201 totPackets 202 .name(name() + ".totPackets") 203 .desc("Total Packets") 204 .precision(0) 205 .prereq(totBytes) 206 ; 207 208 totBytes 209 .name(name() + ".totBytes") 210 .desc("Total Bytes") 211 .precision(0) 212 .prereq(totBytes) 213 ; 214 215 totPacketRate 216 .name(name() + ".totPPS") 217 .desc("Total Tranmission Rate (packets/s)") 218 .precision(0) 219 .prereq(totBytes) 220 ; 221 222 txBytes 223 .name(name() + ".txBytes") 224 .desc("Bytes Transmitted") 225 .prereq(txBytes) 226 ; 227 228 txBandwidth 229 .name(name() + ".txBandwidth") 230 .desc("Transmit Bandwidth (bits/s)") 231 .precision(0) 232 .prereq(txBytes) 233 ; 234 235 txPackets 236 .name(name() + ".txPackets") 237 .desc("Number of Packets Transmitted") 238 .prereq(txBytes) 239 ; 240 241 txPacketRate 242 .name(name() + ".txPPS") 243 .desc("Packet Tranmission Rate (packets/s)") 244 .precision(0) 245 .prereq(txBytes) 246 ; 247 248 txIpPackets 249 .name(name() + ".txIpPackets") 250 .desc("Number of IP Packets Transmitted") 251 .prereq(txBytes) 252 ; 253 254 txTcpPackets 255 .name(name() + ".txTcpPackets") 256 .desc("Number of TCP Packets Transmitted") 257 .prereq(txBytes) 258 ; 259 260 txUdpPackets 261 .name(name() + ".txUdpPackets") 262 .desc("Number of Packets Transmitted") 263 .prereq(txBytes) 264 ; 265 266 txIpChecksums 267 .name(name() + ".txIpChecksums") 268 .desc("Number of tx IP Checksums done by device") 269 .precision(0) 270 .prereq(txBytes) 271 ; 272 273 txTcpChecksums 274 .name(name() + ".txTcpChecksums") 275 .desc("Number of tx TCP Checksums done by device") 276 .precision(0) 277 .prereq(txBytes) 278 ; 279 280 txUdpChecksums 281 .name(name() + ".txUdpChecksums") 282 .desc("Number of tx UDP Checksums done by device") 283 .precision(0) 284 .prereq(txBytes) 285 ; 286 287 txBandwidth = txBytes * Stats::constant(8) / simSeconds; 288 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 289 totBandwidth = txBandwidth + rxBandwidth; 290 totBytes = txBytes + rxBytes; 291 totPackets = txPackets + rxPackets; 292 txPacketRate = txPackets / simSeconds; 293 rxPacketRate = rxPackets / simSeconds; 294} 295 296/** 297 * This is to write to the PCI general configuration registers 298 */ 299void 300Device::writeConfig(int offset, int size, const uint8_t *data) 301{ 302 switch (offset) { 303 case PCI0_BASE_ADDR0: 304 // Need to catch writes to BARs to update the PIO interface 305 PciDev::writeConfig(offset, size, data); 306 if (BARAddrs[0] != 0) { 307 if (pioInterface) 308 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 309 310 BARAddrs[0] &= EV5::PAddrUncachedMask; 311 } 312 break; 313 314 default: 315 PciDev::writeConfig(offset, size, data); 316 } 317} 318 319void 320Device::prepareRead() 321{ 322 using namespace Regs; 323 324 // update rx registers 325 regs.RxDone = set_RxDone_Packets(regs.RxDone, rxFifo.packets()); 326 regs.RxWait = regs.RxDone; 327 328 // update tx regsiters 329 regs.TxDone = set_TxDone_Packets(regs.TxDone, txFifo.packets()); 330 regs.TxDone = set_TxDone_Full(regs.TxDone, 331 txFifo.avail() < regs.TxMaxCopy); 332 regs.TxDone = set_TxDone_Low(regs.TxDone, 333 txFifo.size() < regs.TxFifoMark); 334 regs.TxWait = regs.TxDone; 335} 336 337/** 338 * I/O read of device register 339 */ 340Fault 341Device::read(MemReqPtr &req, uint8_t *data) 342{ 343 assert(config.command & PCI_CMD_MSE); 344 345 //The mask is to give you only the offset into the device register file 346 Addr daddr = req->paddr & 0xfff; 347 348 if (!regValid(daddr)) 349 panic("invalid register: da=%#x pa=%#x va=%#x size=%d", 350 daddr, req->paddr, req->vaddr, req->size); 351 352 const Regs::Info &info = regInfo(daddr); 353 if (!info.read) 354 panic("reading write only register: %s: da=%#x pa=%#x va=%#x size=%d", 355 info.name, daddr, req->paddr, req->vaddr, req->size); 356 357 if (req->size != info.size) 358 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", 359 info.name, daddr, req->paddr, req->vaddr, req->size); 360 361 prepareRead(); 362 363 uint64_t value = 0; 364 if (req->size == 4) { 365 uint32_t ® = *(uint32_t *)data; 366 reg = regData32(daddr); 367 value = reg; 368 } 369 370 if (req->size == 8) { 371 uint64_t ® = *(uint64_t *)data; 372 reg = regData64(daddr); 373 value = reg; 374 } 375 376 DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d val=%#x\n", 377 info.name, daddr, req->paddr, req->vaddr, req->size, value); 378 379 // reading the interrupt status register has the side effect of 380 // clearing it 381 if (daddr == Regs::IntrStatus) 382 devIntrClear(); 383 384 return No_Fault; 385} 386 387/** 388 * IPR read of device register 389 */ 390Fault 391Device::iprRead(Addr daddr, uint64_t &result) 392{ 393 if (!regValid(daddr)) 394 panic("invalid address: da=%#x", daddr); 395 396 const Regs::Info &info = regInfo(daddr); 397 if (!info.read) 398 panic("reading write only register %s: da=%#x", info.name, daddr); 399 400 DPRINTF(EthernetPIO, "read reg=%s da=%#x\n", info.name, daddr); 401 402 prepareRead(); 403 404 if (info.size == 4) 405 result = regData32(daddr); 406 407 if (info.size == 8) 408 result = regData64(daddr); 409 410 DPRINTF(EthernetPIO, "IPR read reg=%s da=%#x val=%#x\n", 411 info.name, result); 412 413 return No_Fault; 414} 415 416/** 417 * I/O write of device register 418 */ 419Fault 420Device::write(MemReqPtr &req, const uint8_t *data) 421{ 422 assert(config.command & PCI_CMD_MSE); 423 424 //The mask is to give you only the offset into the device register file 425 Addr daddr = req->paddr & 0xfff; 426 427 if (!regValid(daddr)) 428 panic("invalid address: da=%#x pa=%#x va=%#x size=%d", 429 daddr, req->paddr, req->vaddr, req->size); 430 431 const Regs::Info &info = regInfo(daddr); 432 if (!info.write) 433 panic("writing read only register %s: da=%#x", info.name, daddr); 434 435 if (req->size != info.size) 436 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", 437 info.name, daddr, req->paddr, req->vaddr, req->size); 438 439 uint32_t reg32 = *(uint32_t *)data; 440 uint64_t reg64 = *(uint64_t *)data; 441 442 DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n", 443 info.name, info.size == 4 ? reg32 : reg64, daddr, req->paddr, 444 req->vaddr, req->size); 445 446 switch (daddr) { 447 case Regs::Config: 448 changeConfig(reg32); 449 break; 450 451 case Regs::Command: 452 command(reg32); 453 break; 454 455 case Regs::IntrStatus: 456 devIntrClear(regs.IntrStatus & reg32); 457 break; 458 459 case Regs::IntrMask: 460 devIntrChangeMask(reg32); 461 break; 462 463 case Regs::RxData: 464 if (rxState != rxIdle) 465 panic("receive machine busy with another request! rxState=%s", 466 RxStateStrings[rxState]); 467 468 regs.RxDone = Regs::RxDone_Busy; 469 regs.RxData = reg64; 470 if (rxEnable) { 471 rxState = rxFifoBlock; 472 rxKick(); 473 } 474 break; 475 476 case Regs::TxData: 477 if (txState != txIdle) 478 panic("transmit machine busy with another request! txState=%s", 479 TxStateStrings[txState]); 480 481 regs.TxDone = Regs::TxDone_Busy; 482 regs.TxData = reg64; 483 if (txEnable) { 484 txState = txFifoBlock; 485 txKick(); 486 } 487 break; 488 } 489 490 return No_Fault; 491} 492 493void 494Device::devIntrPost(uint32_t interrupts) 495{ 496 if ((interrupts & Regs::Intr_Res)) 497 panic("Cannot set a reserved interrupt"); 498 499 regs.IntrStatus |= interrupts; 500 501 DPRINTF(EthernetIntr, 502 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n", 503 interrupts, regs.IntrStatus, regs.IntrMask); 504 505 interrupts = regs.IntrStatus & regs.IntrMask; 506 507 // Intr_RxHigh is special, we only signal it if we've emptied the fifo 508 // and then filled it above the high watermark 509 if (rxEmpty) 510 rxEmpty = false; 511 else 512 interrupts &= ~Regs::Intr_RxHigh; 513 514 // Intr_TxLow is special, we only signal it if we've filled up the fifo 515 // and then dropped below the low watermark 516 if (txFull) 517 txFull = false; 518 else 519 interrupts &= ~Regs::Intr_TxLow; 520 521 if (interrupts) { 522 Tick when = curTick; 523 if ((interrupts & Regs::Intr_NoDelay) == 0) 524 when += intrDelay; 525 cpuIntrPost(when); 526 } 527} 528 529void 530Device::devIntrClear(uint32_t interrupts) 531{ 532 if ((interrupts & Regs::Intr_Res)) 533 panic("Cannot clear a reserved interrupt"); 534 535 regs.IntrStatus &= ~interrupts; 536 537 DPRINTF(EthernetIntr, 538 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n", 539 interrupts, regs.IntrStatus, regs.IntrMask); 540 541 if (!(regs.IntrStatus & regs.IntrMask)) 542 cpuIntrClear(); 543} 544 545void 546Device::devIntrChangeMask(uint32_t newmask) 547{ 548 if (regs.IntrMask == newmask) 549 return; 550 551 regs.IntrMask = newmask; 552 553 DPRINTF(EthernetIntr, 554 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n", 555 regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask); 556 557 if (regs.IntrStatus & regs.IntrMask) 558 cpuIntrPost(curTick); 559 else 560 cpuIntrClear(); 561} 562 563void 564Base::cpuIntrPost(Tick when) 565{ 566 // If the interrupt you want to post is later than an interrupt 567 // already scheduled, just let it post in the coming one and don't 568 // schedule another. 569 // HOWEVER, must be sure that the scheduled intrTick is in the 570 // future (this was formerly the source of a bug) 571 /** 572 * @todo this warning should be removed and the intrTick code should 573 * be fixed. 574 */ 575 assert(when >= curTick); 576 assert(intrTick >= curTick || intrTick == 0); 577 if (!cpuIntrEnable) { 578 DPRINTF(EthernetIntr, "interrupts not enabled.\n", 579 intrTick); 580 return; 581 } 582 583 if (when > intrTick && intrTick != 0) { 584 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 585 intrTick); 586 return; 587 } 588 589 intrTick = when; 590 if (intrTick < curTick) { 591 debug_break(); 592 intrTick = curTick; 593 } 594 595 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 596 intrTick); 597 598 if (intrEvent) 599 intrEvent->squash(); 600 intrEvent = new IntrEvent(this, true); 601 intrEvent->schedule(intrTick); 602} 603 604void 605Base::cpuInterrupt() 606{ 607 assert(intrTick == curTick); 608 609 // Whether or not there's a pending interrupt, we don't care about 610 // it anymore 611 intrEvent = 0; 612 intrTick = 0; 613 614 // Don't send an interrupt if there's already one 615 if (cpuPendingIntr) { 616 DPRINTF(EthernetIntr, 617 "would send an interrupt now, but there's already pending\n"); 618 } else { 619 // Send interrupt 620 cpuPendingIntr = true; 621 622 DPRINTF(EthernetIntr, "posting interrupt\n"); 623 intrPost(); 624 } 625} 626 627void 628Base::cpuIntrClear() 629{ 630 if (!cpuPendingIntr) 631 return; 632 633 if (intrEvent) { 634 intrEvent->squash(); 635 intrEvent = 0; 636 } 637 638 intrTick = 0; 639 640 cpuPendingIntr = false; 641 642 DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); 643 intrClear(); 644} 645 646bool 647Base::cpuIntrPending() const 648{ return cpuPendingIntr; } 649 650void 651Device::changeConfig(uint32_t newconf) 652{ 653 uint32_t changed = regs.Config ^ newconf; 654 if (!changed) 655 return; 656 657 regs.Config = newconf; 658 659 if ((changed & Regs::Config_IntEn)) { 660 cpuIntrEnable = regs.Config & Regs::Config_IntEn; 661 if (cpuIntrEnable) { 662 if (regs.IntrStatus & regs.IntrMask) 663 cpuIntrPost(curTick); 664 } else { 665 cpuIntrClear(); 666 } 667 } 668 669 if ((changed & Regs::Config_TxEn)) { 670 txEnable = regs.Config & Regs::Config_TxEn; 671 if (txEnable) 672 txKick(); 673 } 674 675 if ((changed & Regs::Config_RxEn)) { 676 rxEnable = regs.Config & Regs::Config_RxEn; 677 if (rxEnable) 678 rxKick(); 679 } 680} 681 682void 683Device::command(uint32_t command) 684{ 685 if (command & Regs::Command_Reset) 686 reset(); 687} 688 689void 690Device::reset() 691{ 692 using namespace Regs; 693 694 memset(®s, 0, sizeof(regs)); 695 696 regs.Config = 0; 697 if (params()->dedicated) 698 regs.Config |= Config_Thread; 699 regs.IntrMask = Intr_RxHigh | Intr_RxDMA | Intr_TxLow; 700 regs.RxMaxCopy = params()->rx_max_copy; 701 regs.TxMaxCopy = params()->tx_max_copy; 702 regs.RxMaxIntr = params()->rx_max_intr; 703 regs.RxFifoSize = params()->rx_fifo_size; 704 regs.TxFifoSize = params()->tx_fifo_size; 705 regs.RxFifoMark = params()->rx_fifo_threshold; 706 regs.TxFifoMark = params()->tx_fifo_threshold; 707 regs.HwAddr = params()->eaddr; 708 709 rxState = rxIdle; 710 txState = txIdle; 711 712 rxFifo.clear(); 713 txFifo.clear(); 714 rxEmpty = false; 715 txFull = false; 716} 717 718void 719Device::rxDmaCopy() 720{ 721 assert(rxState == rxCopy); 722 rxState = rxCopyDone; 723 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 724 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 725 rxDmaAddr, rxDmaLen); 726 DDUMP(EthernetData, rxDmaData, rxDmaLen); 727} 728 729void 730Device::rxDmaDone() 731{ 732 rxDmaCopy(); 733 734 // If the transmit state machine has a pending DMA, let it go first 735 if (txState == txBeginCopy) 736 txKick(); 737 738 rxKick(); 739} 740 741void 742Device::rxKick() 743{ 744 DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n", 745 RxStateStrings[rxState], rxFifo.size()); 746 747 if (rxKickTick > curTick) { 748 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 749 rxKickTick); 750 return; 751 } 752 753 next: 754 switch (rxState) { 755 case rxIdle: 756 if (rxPioRequest) { 757 DPRINTF(EthernetPIO, "rxIdle: PIO waiting responding at %d\n", 758 curTick + pioLatency); 759 pioInterface->respond(rxPioRequest, curTick); 760 rxPioRequest = 0; 761 } 762 goto exit; 763 764 case rxFifoBlock: 765 if (rxPacket) { 766 rxState = rxBeginCopy; 767 break; 768 } 769 770 if (rxFifo.empty()) { 771 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n"); 772 goto exit; 773 } 774 775 // Grab a new packet from the fifo. 776 rxPacket = rxFifo.front(); 777 rxPacketBufPtr = rxPacket->data; 778 rxPktBytes = rxPacket->length; 779 assert(rxPktBytes); 780 781 rxDoneData = 0; 782 /* scope for variables */ { 783 IpPtr ip(rxPacket); 784 if (ip) { 785 rxDoneData |= Regs::RxDone_IpPacket; 786 rxIpChecksums++; 787 if (cksum(ip) != 0) { 788 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 789 rxDoneData |= Regs::RxDone_IpError; 790 } 791 TcpPtr tcp(ip); 792 UdpPtr udp(ip); 793 if (tcp) { 794 rxDoneData |= Regs::RxDone_TcpPacket; 795 rxTcpChecksums++; 796 if (cksum(tcp) != 0) { 797 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 798 rxDoneData |= Regs::RxDone_TcpError; 799 } 800 } else if (udp) { 801 rxDoneData |= Regs::RxDone_UdpPacket; 802 rxUdpChecksums++; 803 if (cksum(udp) != 0) { 804 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 805 rxDoneData |= Regs::RxDone_UdpError; 806 } 807 } 808 } 809 } 810 rxState = rxBeginCopy; 811 break; 812 813 case rxBeginCopy: 814 if (dmaInterface && dmaInterface->busy()) 815 goto exit; 816 817 rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData)); 818 rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes); 819 rxDmaData = rxPacketBufPtr; 820 rxState = rxCopy; 821 822 if (dmaInterface) { 823 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, 824 curTick, &rxDmaEvent, true); 825 goto exit; 826 } 827 828 if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { 829 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 830 Tick start = curTick + dmaWriteDelay + factor; 831 rxDmaEvent.schedule(start); 832 goto exit; 833 } 834 835 rxDmaCopy(); 836 break; 837 838 case rxCopy: 839 DPRINTF(EthernetSM, "receive machine still copying\n"); 840 goto exit; 841 842 case rxCopyDone: 843 regs.RxDone = rxDoneData | rxDmaLen; 844 845 if (rxPktBytes == rxDmaLen) { 846 rxPacket = NULL; 847 rxFifo.pop(); 848 } else { 849 regs.RxDone |= Regs::RxDone_More; 850 rxPktBytes -= rxDmaLen; 851 rxPacketBufPtr += rxDmaLen; 852 } 853 854 regs.RxDone |= Regs::RxDone_Complete; 855 devIntrPost(Regs::Intr_RxDMA); 856 rxState = rxIdle; 857 break; 858 859 default: 860 panic("Invalid rxState!"); 861 } 862 863 DPRINTF(EthernetSM, "entering next rxState=%s\n", 864 RxStateStrings[rxState]); 865 866 goto next; 867 868 exit: 869 /** 870 * @todo do we want to schedule a future kick? 871 */ 872 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 873 RxStateStrings[rxState]); 874} 875 876void 877Device::txDmaCopy() 878{ 879 assert(txState == txCopy); 880 txState = txCopyDone; 881 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 882 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 883 txDmaAddr, txDmaLen); 884 DDUMP(EthernetData, txDmaData, txDmaLen); 885} 886 887void 888Device::txDmaDone() 889{ 890 txDmaCopy(); 891 892 // If the receive state machine has a pending DMA, let it go first 893 if (rxState == rxBeginCopy) 894 rxKick(); 895 896 txKick(); 897} 898 899void 900Device::transmit() 901{ 902 if (txFifo.empty()) { 903 DPRINTF(Ethernet, "nothing to transmit\n"); 904 return; 905 } 906 907 uint32_t interrupts; 908 PacketPtr packet = txFifo.front(); 909 if (!interface->sendPacket(packet)) { 910 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", 911 txFifo.avail()); 912 goto reschedule; 913 } 914 915 txFifo.pop(); 916#if TRACING_ON 917 if (DTRACE(Ethernet)) { 918 IpPtr ip(packet); 919 if (ip) { 920 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 921 TcpPtr tcp(ip); 922 if (tcp) { 923 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 924 tcp->sport(), tcp->dport()); 925 } 926 } 927 } 928#endif 929 930 DDUMP(EthernetData, packet->data, packet->length); 931 txBytes += packet->length; 932 txPackets++; 933 934 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", 935 txFifo.avail()); 936 937 interrupts = Regs::Intr_TxPacket; 938 if (txFifo.size() < regs.TxFifoMark) 939 interrupts |= Regs::Intr_TxLow; 940 devIntrPost(interrupts); 941 942 reschedule: 943 if (!txFifo.empty() && !txEvent.scheduled()) { 944 DPRINTF(Ethernet, "reschedule transmit\n"); 945 txEvent.schedule(curTick + retryTime); 946 } 947} 948 949void 950Device::txKick() 951{ 952 DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n", 953 TxStateStrings[txState], txFifo.size()); 954 955 if (txKickTick > curTick) { 956 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 957 txKickTick); 958 return; 959 } 960 961 next: 962 switch (txState) { 963 case txIdle: 964 if (txPioRequest) { 965 DPRINTF(EthernetPIO, "txIdle: PIO waiting responding at %d\n", 966 curTick + pioLatency); 967 pioInterface->respond(txPioRequest, curTick + pioLatency); 968 txPioRequest = 0; 969 } 970 goto exit; 971 972 case txFifoBlock: 973 if (!txPacket) { 974 // Grab a new packet from the fifo. 975 txPacket = new PacketData(16384); 976 txPacketBufPtr = txPacket->data; 977 } 978 979 if (txFifo.avail() - txPacket->length < 980 Regs::get_TxData_Len(regs.TxData)) { 981 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n"); 982 goto exit; 983 } 984 985 txState = txBeginCopy; 986 break; 987 988 case txBeginCopy: 989 if (dmaInterface && dmaInterface->busy()) 990 goto exit; 991 992 txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData)); 993 txDmaLen = Regs::get_TxData_Len(regs.TxData); 994 txDmaData = txPacketBufPtr; 995 txState = txCopy; 996 997 if (dmaInterface) { 998 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, 999 curTick, &txDmaEvent, true); 1000 goto exit; 1001 } 1002 1003 if (dmaReadDelay != 0 || dmaReadFactor != 0) { 1004 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1005 Tick start = curTick + dmaReadDelay + factor; 1006 txDmaEvent.schedule(start); 1007 goto exit; 1008 } 1009 1010 txDmaCopy(); 1011 break; 1012 1013 case txCopy: 1014 DPRINTF(EthernetSM, "transmit machine still copying\n"); 1015 goto exit; 1016 1017 case txCopyDone: 1018 txPacket->length += txDmaLen; 1019 if ((regs.TxData & Regs::TxData_More)) { 1020 txPacketBufPtr += txDmaLen; 1021 } else { 1022 assert(txPacket->length <= txFifo.avail()); 1023 if ((regs.TxData & Regs::TxData_Checksum)) { 1024 IpPtr ip(txPacket); 1025 if (ip) { 1026 TcpPtr tcp(ip); 1027 if (tcp) { 1028 tcp->sum(0); 1029 tcp->sum(cksum(tcp)); 1030 txTcpChecksums++; 1031 } 1032 1033 UdpPtr udp(ip); 1034 if (udp) { 1035 udp->sum(0); 1036 udp->sum(cksum(udp)); 1037 txUdpChecksums++; 1038 } 1039 1040 ip->sum(0); 1041 ip->sum(cksum(ip)); 1042 txIpChecksums++; 1043 } 1044 } 1045 txFifo.push(txPacket); 1046 if (txFifo.avail() < regs.TxMaxCopy) { 1047 devIntrPost(Regs::Intr_TxFull); 1048 txFull = true; 1049 } 1050 txPacket = 0; 1051 transmit(); 1052 } 1053 1054 regs.TxDone = txDmaLen | Regs::TxDone_Complete; 1055 devIntrPost(Regs::Intr_TxDMA); 1056 txState = txIdle; 1057 break; 1058 1059 default: 1060 panic("Invalid txState!"); 1061 } 1062 1063 DPRINTF(EthernetSM, "entering next txState=%s\n", 1064 TxStateStrings[txState]); 1065 1066 goto next; 1067 1068 exit: 1069 /** 1070 * @todo do we want to schedule a future kick? 1071 */ 1072 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1073 TxStateStrings[txState]); 1074} 1075 1076void 1077Device::transferDone() 1078{ 1079 if (txFifo.empty()) { 1080 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1081 return; 1082 } 1083 1084 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1085 1086 if (txEvent.scheduled()) 1087 txEvent.reschedule(curTick + cycles(1)); 1088 else 1089 txEvent.schedule(curTick + cycles(1)); 1090} 1091 1092bool 1093Device::rxFilter(const PacketPtr &packet) 1094{ 1095 if (!Regs::get_Config_Filter(regs.Config)) 1096 return false; 1097 1098 panic("receive filter not implemented\n"); 1099 bool drop = true; 1100 1101#if 0 1102 string type; 1103 1104 EthHdr *eth = packet->eth(); 1105 if (eth->unicast()) { 1106 // If we're accepting all unicast addresses 1107 if (acceptUnicast) 1108 drop = false; 1109 1110 // If we make a perfect match 1111 if (acceptPerfect && params->eaddr == eth.dst()) 1112 drop = false; 1113 1114 if (acceptArp && eth->type() == ETH_TYPE_ARP) 1115 drop = false; 1116 1117 } else if (eth->broadcast()) { 1118 // if we're accepting broadcasts 1119 if (acceptBroadcast) 1120 drop = false; 1121 1122 } else if (eth->multicast()) { 1123 // if we're accepting all multicasts 1124 if (acceptMulticast) 1125 drop = false; 1126 1127 } 1128 1129 if (drop) { 1130 DPRINTF(Ethernet, "rxFilter drop\n"); 1131 DDUMP(EthernetData, packet->data, packet->length); 1132 } 1133#endif 1134 return drop; 1135} 1136 1137bool 1138Device::recvPacket(PacketPtr packet) 1139{ 1140 rxBytes += packet->length; 1141 rxPackets++; 1142 1143 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n", 1144 rxFifo.avail()); 1145 1146 if (!rxEnable) { 1147 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1148 return true; 1149 } 1150 1151 if (rxFilter(packet)) { 1152 DPRINTF(Ethernet, "packet filtered...dropped\n"); 1153 return true; 1154 } 1155 1156 if (rxFifo.size() >= regs.RxFifoMark) 1157 devIntrPost(Regs::Intr_RxHigh); 1158 1159 if (!rxFifo.push(packet)) { 1160 DPRINTF(Ethernet, 1161 "packet will not fit in receive buffer...packet dropped\n"); 1162 return false; 1163 } 1164 1165 devIntrPost(Regs::Intr_RxPacket); 1166 rxKick(); 1167 return true; 1168} 1169 1170//===================================================================== 1171// 1172// 1173void 1174Base::serialize(ostream &os) 1175{ 1176 // Serialize the PciDev base class 1177 PciDev::serialize(os); 1178 1179 SERIALIZE_SCALAR(rxEnable); 1180 SERIALIZE_SCALAR(txEnable); 1181 SERIALIZE_SCALAR(cpuIntrEnable); 1182 1183 /* 1184 * Keep track of pending interrupt status. 1185 */ 1186 SERIALIZE_SCALAR(intrTick); 1187 SERIALIZE_SCALAR(cpuPendingIntr); 1188 Tick intrEventTick = 0; 1189 if (intrEvent) 1190 intrEventTick = intrEvent->when(); 1191 SERIALIZE_SCALAR(intrEventTick); 1192} 1193 1194void 1195Base::unserialize(Checkpoint *cp, const std::string §ion) 1196{ 1197 // Unserialize the PciDev base class 1198 PciDev::unserialize(cp, section); 1199 1200 UNSERIALIZE_SCALAR(rxEnable); 1201 UNSERIALIZE_SCALAR(txEnable); 1202 UNSERIALIZE_SCALAR(cpuIntrEnable); 1203 1204 /* 1205 * Keep track of pending interrupt status. 1206 */ 1207 UNSERIALIZE_SCALAR(intrTick); 1208 UNSERIALIZE_SCALAR(cpuPendingIntr); 1209 Tick intrEventTick; 1210 UNSERIALIZE_SCALAR(intrEventTick); 1211 if (intrEventTick) { 1212 intrEvent = new IntrEvent(this, true); 1213 intrEvent->schedule(intrEventTick); 1214 } 1215} 1216 1217void 1218Device::serialize(ostream &os) 1219{ 1220 // Serialize the PciDev base class 1221 Base::serialize(os); 1222 1223 if (rxState == rxCopy) 1224 panic("can't serialize with an in flight dma request rxState=%s", 1225 RxStateStrings[rxState]); 1226 1227 if (txState == txCopy) 1228 panic("can't serialize with an in flight dma request txState=%s", 1229 TxStateStrings[txState]); 1230 1231 /* 1232 * Serialize the device registers 1233 */ 1234 SERIALIZE_SCALAR(regs.Config); 1235 SERIALIZE_SCALAR(regs.IntrStatus); 1236 SERIALIZE_SCALAR(regs.IntrMask); 1237 SERIALIZE_SCALAR(regs.RxMaxCopy); 1238 SERIALIZE_SCALAR(regs.TxMaxCopy); 1239 SERIALIZE_SCALAR(regs.RxMaxIntr); 1240 SERIALIZE_SCALAR(regs.RxData); 1241 SERIALIZE_SCALAR(regs.RxDone); 1242 SERIALIZE_SCALAR(regs.TxData); 1243 SERIALIZE_SCALAR(regs.TxDone); 1244 1245 /* 1246 * Serialize rx state machine 1247 */ 1248 int rxState = this->rxState; 1249 SERIALIZE_SCALAR(rxState); 1250 SERIALIZE_SCALAR(rxEmpty); 1251 rxFifo.serialize("rxFifo", os); 1252 bool rxPacketExists = rxPacket; 1253 SERIALIZE_SCALAR(rxPacketExists); 1254 if (rxPacketExists) { 1255 rxPacket->serialize("rxPacket", os); 1256 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 1257 SERIALIZE_SCALAR(rxPktBufPtr); 1258 SERIALIZE_SCALAR(rxPktBytes); 1259 } 1260 SERIALIZE_SCALAR(rxDoneData); 1261 1262 /* 1263 * Serialize tx state machine 1264 */ 1265 int txState = this->txState; 1266 SERIALIZE_SCALAR(txState); 1267 SERIALIZE_SCALAR(txFull); 1268 txFifo.serialize("txFifo", os); 1269 bool txPacketExists = txPacket; 1270 SERIALIZE_SCALAR(txPacketExists); 1271 if (txPacketExists) { 1272 txPacket->serialize("txPacket", os); 1273 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 1274 SERIALIZE_SCALAR(txPktBufPtr); 1275 SERIALIZE_SCALAR(txPktBytes); 1276 } 1277 1278 /* 1279 * If there's a pending transmit, store the time so we can 1280 * reschedule it later 1281 */ 1282 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 1283 SERIALIZE_SCALAR(transmitTick); 1284} 1285 1286void 1287Device::unserialize(Checkpoint *cp, const std::string §ion) 1288{ 1289 // Unserialize the PciDev base class 1290 Base::unserialize(cp, section); 1291 1292 /* 1293 * Unserialize the device registers 1294 */ 1295 UNSERIALIZE_SCALAR(regs.Config); 1296 UNSERIALIZE_SCALAR(regs.IntrStatus); 1297 UNSERIALIZE_SCALAR(regs.IntrMask); 1298 UNSERIALIZE_SCALAR(regs.RxMaxCopy); 1299 UNSERIALIZE_SCALAR(regs.TxMaxCopy); 1300 UNSERIALIZE_SCALAR(regs.RxMaxIntr); 1301 UNSERIALIZE_SCALAR(regs.RxData); 1302 UNSERIALIZE_SCALAR(regs.RxDone); 1303 UNSERIALIZE_SCALAR(regs.TxData); 1304 UNSERIALIZE_SCALAR(regs.TxDone); 1305 1306 /* 1307 * Unserialize rx state machine 1308 */ 1309 int rxState; 1310 UNSERIALIZE_SCALAR(rxState); 1311 UNSERIALIZE_SCALAR(rxEmpty); 1312 this->rxState = (RxState) rxState; 1313 rxFifo.unserialize("rxFifo", cp, section); 1314 bool rxPacketExists; 1315 UNSERIALIZE_SCALAR(rxPacketExists); 1316 rxPacket = 0; 1317 if (rxPacketExists) { 1318 rxPacket = new PacketData(16384); 1319 rxPacket->unserialize("rxPacket", cp, section); 1320 uint32_t rxPktBufPtr; 1321 UNSERIALIZE_SCALAR(rxPktBufPtr); 1322 this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 1323 UNSERIALIZE_SCALAR(rxPktBytes); 1324 } 1325 UNSERIALIZE_SCALAR(rxDoneData); 1326 1327 /* 1328 * Unserialize tx state machine 1329 */ 1330 int txState; 1331 UNSERIALIZE_SCALAR(txState); 1332 UNSERIALIZE_SCALAR(txFull); 1333 this->txState = (TxState) txState; 1334 txFifo.unserialize("txFifo", cp, section); 1335 bool txPacketExists; 1336 UNSERIALIZE_SCALAR(txPacketExists); 1337 txPacket = 0; 1338 if (txPacketExists) { 1339 txPacket = new PacketData(16384); 1340 txPacket->unserialize("txPacket", cp, section); 1341 uint32_t txPktBufPtr; 1342 UNSERIALIZE_SCALAR(txPktBufPtr); 1343 this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 1344 UNSERIALIZE_SCALAR(txPktBytes); 1345 } 1346 1347 /* 1348 * If there's a pending transmit, reschedule it now 1349 */ 1350 Tick transmitTick; 1351 UNSERIALIZE_SCALAR(transmitTick); 1352 if (transmitTick) 1353 txEvent.schedule(curTick + transmitTick); 1354 1355 /* 1356 * re-add addrRanges to bus bridges 1357 */ 1358 if (pioInterface) 1359 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 1360} 1361 1362Tick 1363Device::cacheAccess(MemReqPtr &req) 1364{ 1365 //The mask is to give you only the offset into the device register file 1366 Addr daddr = req->paddr - addr; 1367 1368 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 1369 req->paddr, daddr); 1370 1371 Tick when = curTick + pioLatency; 1372 1373 switch (daddr) { 1374 case Regs::RxWait: 1375 if (rxState != rxIdle) { 1376 DPRINTF(EthernetPIO, "rxState=%s (not idle)... waiting\n", 1377 TxStateStrings[txState]); 1378 rxPioRequest = req; 1379 when = 0; 1380 } 1381 break; 1382 1383 case Regs::TxWait: 1384 if (txState != txIdle) { 1385 DPRINTF(EthernetPIO, "txState=%s (not idle)... waiting\n", 1386 TxStateStrings[txState]); 1387 txPioRequest = req; 1388 when = 0; 1389 } 1390 break; 1391 } 1392 1393 return when; 1394} 1395 1396BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) 1397 1398 SimObjectParam<EtherInt *> peer; 1399 SimObjectParam<Device *> device; 1400 1401END_DECLARE_SIM_OBJECT_PARAMS(Interface) 1402 1403BEGIN_INIT_SIM_OBJECT_PARAMS(Interface) 1404 1405 INIT_PARAM_DFLT(peer, "peer interface", NULL), 1406 INIT_PARAM(device, "Ethernet device of this interface") 1407 1408END_INIT_SIM_OBJECT_PARAMS(Interface) 1409 1410CREATE_SIM_OBJECT(Interface) 1411{ 1412 Interface *dev_int = new Interface(getInstanceName(), device); 1413 1414 EtherInt *p = (EtherInt *)peer; 1415 if (p) { 1416 dev_int->setPeer(p); 1417 p->setPeer(dev_int); 1418 } 1419 1420 return dev_int; 1421} 1422 1423REGISTER_SIM_OBJECT("SinicInt", Interface) 1424 1425 1426BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) 1427 1428 Param<Tick> clock; 1429 1430 Param<Addr> addr; 1431 SimObjectParam<MemoryController *> mmu; 1432 SimObjectParam<PhysicalMemory *> physmem; 1433 SimObjectParam<PciConfigAll *> configspace; 1434 SimObjectParam<PciConfigData *> configdata; 1435 SimObjectParam<Platform *> platform; 1436 Param<uint32_t> pci_bus; 1437 Param<uint32_t> pci_dev; 1438 Param<uint32_t> pci_func; 1439 1440 SimObjectParam<HierParams *> hier; 1441 SimObjectParam<Bus*> io_bus; 1442 SimObjectParam<Bus*> payload_bus; 1443 Param<Tick> dma_read_delay; 1444 Param<Tick> dma_read_factor; 1445 Param<Tick> dma_write_delay; 1446 Param<Tick> dma_write_factor; 1447 Param<bool> dma_no_allocate; 1448 Param<Tick> pio_latency; 1449 Param<Tick> intr_delay; 1450 1451 Param<Tick> rx_delay; 1452 Param<Tick> tx_delay; 1453 Param<uint32_t> rx_max_copy; 1454 Param<uint32_t> tx_max_copy; 1455 Param<uint32_t> rx_max_intr; 1456 Param<uint32_t> rx_fifo_size; 1457 Param<uint32_t> tx_fifo_size; 1458 Param<uint32_t> rx_fifo_threshold; 1459 Param<uint32_t> tx_fifo_threshold; 1460 1461 Param<bool> rx_filter; 1462 Param<string> hardware_address; 1463 Param<bool> dedicated; 1464 1465END_DECLARE_SIM_OBJECT_PARAMS(Device) 1466 1467BEGIN_INIT_SIM_OBJECT_PARAMS(Device) 1468 1469 INIT_PARAM(clock, "State machine cycle time"), 1470 1471 INIT_PARAM(addr, "Device Address"), 1472 INIT_PARAM(mmu, "Memory Controller"), 1473 INIT_PARAM(physmem, "Physical Memory"), 1474 INIT_PARAM(configspace, "PCI Configspace"), 1475 INIT_PARAM(configdata, "PCI Config data"), 1476 INIT_PARAM(platform, "Platform"), 1477 INIT_PARAM(pci_bus, "PCI bus"), 1478 INIT_PARAM(pci_dev, "PCI device number"), 1479 INIT_PARAM(pci_func, "PCI function code"), 1480 1481 INIT_PARAM(hier, "Hierarchy global variables"), 1482 INIT_PARAM(io_bus, "The IO Bus to attach to for headers"), 1483 INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), 1484 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 1485 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 1486 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 1487 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 1488 INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), 1489 INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), 1490 INIT_PARAM(intr_delay, "Interrupt Delay"), 1491 1492 INIT_PARAM(rx_delay, "Receive Delay"), 1493 INIT_PARAM(tx_delay, "Transmit Delay"), 1494 INIT_PARAM(rx_max_copy, "rx max copy"), 1495 INIT_PARAM(tx_max_copy, "rx max copy"), 1496 INIT_PARAM(rx_max_intr, "rx max intr"), 1497 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 1498 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 1499 INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"), 1500 INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"), 1501 1502 INIT_PARAM(rx_filter, "Enable Receive Filter"), 1503 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 1504 INIT_PARAM(dedicated, "dedicate a kernel thread to the driver") 1505 1506END_INIT_SIM_OBJECT_PARAMS(Device) 1507 1508 1509CREATE_SIM_OBJECT(Device) 1510{ 1511 Device::Params *params = new Device::Params; 1512 1513 params->name = getInstanceName(); 1514 1515 params->clock = clock; 1516 1517 params->mmu = mmu; 1518 params->physmem = physmem; 1519 params->configSpace = configspace; 1520 params->configData = configdata; 1521 params->plat = platform; 1522 params->busNum = pci_bus; 1523 params->deviceNum = pci_dev; 1524 params->functionNum = pci_func; 1525 1526 params->hier = hier; 1527 params->io_bus = io_bus; 1528 params->payload_bus = payload_bus; 1529 params->dma_read_delay = dma_read_delay; 1530 params->dma_read_factor = dma_read_factor; 1531 params->dma_write_delay = dma_write_delay; 1532 params->dma_write_factor = dma_write_factor; 1533 params->dma_no_allocate = dma_no_allocate; 1534 params->pio_latency = pio_latency; 1535 params->intr_delay = intr_delay; 1536 1537 params->tx_delay = tx_delay; 1538 params->rx_delay = rx_delay; 1539 params->rx_max_copy = rx_max_copy; 1540 params->tx_max_copy = tx_max_copy; 1541 params->rx_max_intr = rx_max_intr; 1542 params->rx_fifo_size = rx_fifo_size; 1543 params->tx_fifo_size = tx_fifo_size; 1544 params->rx_fifo_threshold = rx_fifo_threshold; 1545 params->tx_fifo_threshold = tx_fifo_threshold; 1546 1547 params->rx_filter = rx_filter; 1548 params->eaddr = hardware_address; 1549 params->dedicated = dedicated; 1550 1551 return new Device(params); 1552} 1553 1554REGISTER_SIM_OBJECT("Sinic", Device) 1555 1556/* namespace Sinic */ } 1557