Add the capability to iterate through the packets in a pktfifo,
[gem5.git] / dev / ide_ctrl.cc
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
29 #include <cstddef>
30 #include <cstdlib>
31 #include <string>
32 #include <vector>
33
34 #include "base/trace.hh"
35 #include "cpu/intr_control.hh"
36 #include "dev/ide_ctrl.hh"
37 #include "dev/ide_disk.hh"
38 #include "dev/pciconfigall.hh"
39 #include "dev/pcireg.h"
40 #include "dev/platform.hh"
41 #include "mem/bus/bus.hh"
42 #include "mem/bus/dma_interface.hh"
43 #include "mem/bus/pio_interface.hh"
44 #include "mem/bus/pio_interface_impl.hh"
45 #include "mem/functional/memory_control.hh"
46 #include "mem/functional/physical.hh"
47 #include "sim/builder.hh"
48 #include "sim/sim_object.hh"
49
50 using namespace std;
51
52 ////
53 // Initialization and destruction
54 ////
55
56 IdeController::IdeController(Params *p)
57 : PciDev(p)
58 {
59 // initialize the PIO interface addresses
60 pri_cmd_addr = 0;
61 pri_cmd_size = BARSize[0];
62
63 pri_ctrl_addr = 0;
64 pri_ctrl_size = BARSize[1];
65
66 sec_cmd_addr = 0;
67 sec_cmd_size = BARSize[2];
68
69 sec_ctrl_addr = 0;
70 sec_ctrl_size = BARSize[3];
71
72 // initialize the bus master interface (BMI) address to be configured
73 // via PCI
74 bmi_addr = 0;
75 bmi_size = BARSize[4];
76
77 // zero out all of the registers
78 memset(bmi_regs.data, 0, sizeof(bmi_regs));
79 memset(config_regs.data, 0, sizeof(config_regs.data));
80
81 // setup initial values
82 // enable both channels
83 config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN);
84 config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN);
85 bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
86 bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
87
88 // reset all internal variables
89 io_enabled = false;
90 bm_enabled = false;
91 memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
92
93 pioInterface = NULL;
94 dmaInterface = NULL;
95 // create the PIO and DMA interfaces
96 if (params()->pio_bus) {
97 pioInterface = newPioInterface(name() + ".pio", params()->hier,
98 params()->pio_bus, this,
99 &IdeController::cacheAccess);
100 pioLatency = params()->pio_latency * params()->pio_bus->clockRate;
101 }
102
103 if (params()->dma_bus) {
104 dmaInterface = new DMAInterface<Bus>(name() + ".dma",
105 params()->dma_bus,
106 params()->dma_bus, 1, true);
107 }
108
109 // setup the disks attached to controller
110 memset(disks, 0, sizeof(disks));
111 dev[0] = 0;
112 dev[1] = 0;
113
114 if (params()->disks.size() > 3)
115 panic("IDE controllers support a maximum of 4 devices attached!\n");
116
117 for (int i = 0; i < params()->disks.size(); i++) {
118 disks[i] = params()->disks[i];
119 disks[i]->setController(this, dmaInterface);
120 }
121 }
122
123 IdeController::~IdeController()
124 {
125 for (int i = 0; i < 4; i++)
126 if (disks[i])
127 delete disks[i];
128 }
129
130 ////
131 // Utility functions
132 ///
133
134 void
135 IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
136 IdeRegType &reg_type)
137 {
138 offset = addr;
139
140 if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
141 offset -= pri_cmd_addr;
142 reg_type = COMMAND_BLOCK;
143 channel = PRIMARY;
144 } else if (addr >= pri_ctrl_addr &&
145 addr < (pri_ctrl_addr + pri_ctrl_size)) {
146 offset -= pri_ctrl_addr;
147 reg_type = CONTROL_BLOCK;
148 channel = PRIMARY;
149 } else if (addr >= sec_cmd_addr &&
150 addr < (sec_cmd_addr + sec_cmd_size)) {
151 offset -= sec_cmd_addr;
152 reg_type = COMMAND_BLOCK;
153 channel = SECONDARY;
154 } else if (addr >= sec_ctrl_addr &&
155 addr < (sec_ctrl_addr + sec_ctrl_size)) {
156 offset -= sec_ctrl_addr;
157 reg_type = CONTROL_BLOCK;
158 channel = SECONDARY;
159 } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
160 offset -= bmi_addr;
161 reg_type = BMI_BLOCK;
162 channel = (offset < BMIC1) ? PRIMARY : SECONDARY;
163 } else {
164 panic("IDE controller access to invalid address: %#x\n", addr);
165 }
166 }
167
168 int
169 IdeController::getDisk(IdeChannel channel)
170 {
171 int disk = 0;
172 uint8_t *devBit = &dev[0];
173
174 if (channel == SECONDARY) {
175 disk += 2;
176 devBit = &dev[1];
177 }
178
179 disk += *devBit;
180
181 assert(*devBit == 0 || *devBit == 1);
182
183 return disk;
184 }
185
186 int
187 IdeController::getDisk(IdeDisk *diskPtr)
188 {
189 for (int i = 0; i < 4; i++) {
190 if ((long)diskPtr == (long)disks[i])
191 return i;
192 }
193 return -1;
194 }
195
196 bool
197 IdeController::isDiskSelected(IdeDisk *diskPtr)
198 {
199 for (int i = 0; i < 4; i++) {
200 if ((long)diskPtr == (long)disks[i]) {
201 // is disk is on primary or secondary channel
202 int channel = i/2;
203 // is disk the master or slave
204 int devID = i%2;
205
206 return (dev[channel] == devID);
207 }
208 }
209 panic("Unable to find disk by pointer!!\n");
210 }
211
212 ////
213 // Command completion
214 ////
215
216 void
217 IdeController::setDmaComplete(IdeDisk *disk)
218 {
219 int diskNum = getDisk(disk);
220
221 if (diskNum < 0)
222 panic("Unable to find disk based on pointer %#x\n", disk);
223
224 if (diskNum < 2) {
225 // clear the start/stop bit in the command register
226 bmi_regs.bmic0 &= ~SSBM;
227 // clear the bus master active bit in the status register
228 bmi_regs.bmis0 &= ~BMIDEA;
229 // set the interrupt bit
230 bmi_regs.bmis0 |= IDEINTS;
231 } else {
232 // clear the start/stop bit in the command register
233 bmi_regs.bmic1 &= ~SSBM;
234 // clear the bus master active bit in the status register
235 bmi_regs.bmis1 &= ~BMIDEA;
236 // set the interrupt bit
237 bmi_regs.bmis1 |= IDEINTS;
238 }
239 }
240
241 ////
242 // Bus timing and bus access functions
243 ////
244
245 Tick
246 IdeController::cacheAccess(MemReqPtr &req)
247 {
248 // @todo Add more accurate timing to cache access
249 return curTick + pioLatency;
250 }
251
252 ////
253 // Read and write handling
254 ////
255
256 void
257 IdeController::readConfig(int offset, int size, uint8_t *data)
258 {
259 int config_offset;
260
261 if (offset < PCI_DEVICE_SPECIFIC) {
262 PciDev::readConfig(offset, size, data);
263 } else if (offset >= IDE_CTRL_CONF_START &&
264 (offset + size) <= IDE_CTRL_CONF_END) {
265
266 config_offset = offset - IDE_CTRL_CONF_START;
267
268 switch (size) {
269 case sizeof(uint8_t):
270 *data = config_regs.data[config_offset];
271 break;
272 case sizeof(uint16_t):
273 *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset];
274 break;
275 case sizeof(uint32_t):
276 *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset];
277 break;
278 default:
279 panic("Invalid PCI configuration read size!\n");
280 }
281
282 DPRINTF(IdeCtrl, "PCI read offset: %#x size: %#x data: %#x\n",
283 offset, size, *(uint32_t*)data);
284
285 } else {
286 panic("Read of unimplemented PCI config. register: %x\n", offset);
287 }
288 }
289
290 void
291 IdeController::writeConfig(int offset, int size, const uint8_t *data)
292 {
293 int config_offset;
294
295 if (offset < PCI_DEVICE_SPECIFIC) {
296 PciDev::writeConfig(offset, size, data);
297 } else if (offset >= IDE_CTRL_CONF_START &&
298 (offset + size) <= IDE_CTRL_CONF_END) {
299
300 config_offset = offset - IDE_CTRL_CONF_START;
301
302 switch(size) {
303 case sizeof(uint8_t):
304 config_regs.data[config_offset] = *data;
305 break;
306 case sizeof(uint16_t):
307 *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data;
308 break;
309 case sizeof(uint32_t):
310 *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data;
311 break;
312 default:
313 panic("Invalid PCI configuration write size!\n");
314 }
315 } else {
316 panic("Write of unimplemented PCI config. register: %x\n", offset);
317 }
318
319 DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n",
320 offset, size, data);
321
322 // Catch the writes to specific PCI registers that have side affects
323 // (like updating the PIO ranges)
324 switch (offset) {
325 case PCI_COMMAND:
326 if (letoh(config.command) & PCI_CMD_IOSE)
327 io_enabled = true;
328 else
329 io_enabled = false;
330
331 if (letoh(config.command) & PCI_CMD_BME)
332 bm_enabled = true;
333 else
334 bm_enabled = false;
335 break;
336
337 case PCI0_BASE_ADDR0:
338 if (BARAddrs[0] != 0) {
339 pri_cmd_addr = BARAddrs[0];
340 if (pioInterface)
341 pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
342 pri_cmd_size));
343
344 pri_cmd_addr &= EV5::PAddrUncachedMask;
345 }
346 break;
347
348 case PCI0_BASE_ADDR1:
349 if (BARAddrs[1] != 0) {
350 pri_ctrl_addr = BARAddrs[1];
351 if (pioInterface)
352 pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
353 pri_ctrl_size));
354
355 pri_ctrl_addr &= EV5::PAddrUncachedMask;
356 }
357 break;
358
359 case PCI0_BASE_ADDR2:
360 if (BARAddrs[2] != 0) {
361 sec_cmd_addr = BARAddrs[2];
362 if (pioInterface)
363 pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
364 sec_cmd_size));
365
366 sec_cmd_addr &= EV5::PAddrUncachedMask;
367 }
368 break;
369
370 case PCI0_BASE_ADDR3:
371 if (BARAddrs[3] != 0) {
372 sec_ctrl_addr = BARAddrs[3];
373 if (pioInterface)
374 pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
375 sec_ctrl_size));
376
377 sec_ctrl_addr &= EV5::PAddrUncachedMask;
378 }
379 break;
380
381 case PCI0_BASE_ADDR4:
382 if (BARAddrs[4] != 0) {
383 bmi_addr = BARAddrs[4];
384 if (pioInterface)
385 pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
386
387 bmi_addr &= EV5::PAddrUncachedMask;
388 }
389 break;
390 }
391 }
392
393 Fault
394 IdeController::read(MemReqPtr &req, uint8_t *data)
395 {
396 Addr offset;
397 IdeChannel channel;
398 IdeRegType reg_type;
399 int disk;
400
401 parseAddr(req->paddr, offset, channel, reg_type);
402
403 if (!io_enabled)
404 return No_Fault;
405
406 switch (reg_type) {
407 case BMI_BLOCK:
408 switch (req->size) {
409 case sizeof(uint8_t):
410 *data = bmi_regs.data[offset];
411 break;
412 case sizeof(uint16_t):
413 *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset];
414 break;
415 case sizeof(uint32_t):
416 *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset];
417 break;
418 default:
419 panic("IDE read of BMI reg invalid size: %#x\n", req->size);
420 }
421 break;
422
423 case COMMAND_BLOCK:
424 case CONTROL_BLOCK:
425 disk = getDisk(channel);
426
427 if (disks[disk] == NULL)
428 break;
429
430 switch (offset) {
431 case DATA_OFFSET:
432 switch (req->size) {
433 case sizeof(uint16_t):
434 disks[disk]->read(offset, reg_type, data);
435 break;
436
437 case sizeof(uint32_t):
438 disks[disk]->read(offset, reg_type, data);
439 disks[disk]->read(offset, reg_type, &data[2]);
440 break;
441
442 default:
443 panic("IDE read of data reg invalid size: %#x\n", req->size);
444 }
445 break;
446 default:
447 if (req->size == sizeof(uint8_t)) {
448 disks[disk]->read(offset, reg_type, data);
449 } else
450 panic("IDE read of command reg of invalid size: %#x\n", req->size);
451 }
452 break;
453 default:
454 panic("IDE controller read of unknown register block type!\n");
455 }
456
457 DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
458 offset, req->size, *(uint32_t*)data);
459
460 return No_Fault;
461 }
462
463 Fault
464 IdeController::write(MemReqPtr &req, const uint8_t *data)
465 {
466 Addr offset;
467 IdeChannel channel;
468 IdeRegType reg_type;
469 int disk;
470 uint8_t oldVal, newVal;
471
472 parseAddr(req->paddr, offset, channel, reg_type);
473
474 if (!io_enabled)
475 return No_Fault;
476
477 switch (reg_type) {
478 case BMI_BLOCK:
479 if (!bm_enabled)
480 return No_Fault;
481
482 switch (offset) {
483 // Bus master IDE command register
484 case BMIC1:
485 case BMIC0:
486 if (req->size != sizeof(uint8_t))
487 panic("Invalid BMIC write size: %x\n", req->size);
488
489 // select the current disk based on DEV bit
490 disk = getDisk(channel);
491
492 oldVal = bmi_regs.chan[channel].bmic;
493 newVal = *data;
494
495 // if a DMA transfer is in progress, R/W control cannot change
496 if (oldVal & SSBM) {
497 if ((oldVal & RWCON) ^ (newVal & RWCON)) {
498 (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON;
499 }
500 }
501
502 // see if the start/stop bit is being changed
503 if ((oldVal & SSBM) ^ (newVal & SSBM)) {
504 if (oldVal & SSBM) {
505 // stopping DMA transfer
506 DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
507
508 // clear the BMIDEA bit
509 bmi_regs.chan[channel].bmis =
510 bmi_regs.chan[channel].bmis & ~BMIDEA;
511
512 if (disks[disk] == NULL)
513 panic("DMA stop for disk %d which does not exist\n",
514 disk);
515
516 // inform the disk of the DMA transfer abort
517 disks[disk]->abortDma();
518 } else {
519 // starting DMA transfer
520 DPRINTF(IdeCtrl, "Starting DMA transfer\n");
521
522 // set the BMIDEA bit
523 bmi_regs.chan[channel].bmis =
524 bmi_regs.chan[channel].bmis | BMIDEA;
525
526 if (disks[disk] == NULL)
527 panic("DMA start for disk %d which does not exist\n",
528 disk);
529
530 // inform the disk of the DMA transfer start
531 disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp));
532 }
533 }
534
535 // update the register value
536 bmi_regs.chan[channel].bmic = newVal;
537 break;
538
539 // Bus master IDE status register
540 case BMIS0:
541 case BMIS1:
542 if (req->size != sizeof(uint8_t))
543 panic("Invalid BMIS write size: %x\n", req->size);
544
545 oldVal = bmi_regs.chan[channel].bmis;
546 newVal = *data;
547
548 // the BMIDEA bit is RO
549 newVal |= (oldVal & BMIDEA);
550
551 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
552 if ((oldVal & IDEINTS) && (newVal & IDEINTS))
553 newVal &= ~IDEINTS; // clear the interrupt?
554 else
555 (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS;
556
557 if ((oldVal & IDEDMAE) && (newVal & IDEDMAE))
558 newVal &= ~IDEDMAE;
559 else
560 (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
561
562 bmi_regs.chan[channel].bmis = newVal;
563 break;
564
565 // Bus master IDE descriptor table pointer register
566 case BMIDTP0:
567 case BMIDTP1:
568 {
569 if (req->size != sizeof(uint32_t))
570 panic("Invalid BMIDTP write size: %x\n", req->size);
571
572 uint32_t host_data = letoh(*(uint32_t*)data);
573 host_data &= ~0x3;
574 bmi_regs.chan[channel].bmidtp = htole(host_data);
575 }
576 break;
577
578 default:
579 if (req->size != sizeof(uint8_t) &&
580 req->size != sizeof(uint16_t) &&
581 req->size != sizeof(uint32_t))
582 panic("IDE controller write of invalid write size: %x\n",
583 req->size);
584
585 // do a default copy of data into the registers
586 memcpy(&bmi_regs.data[offset], data, req->size);
587 }
588 break;
589 case COMMAND_BLOCK:
590 if (offset == IDE_SELECT_OFFSET) {
591 uint8_t *devBit = &dev[channel];
592 *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0;
593 }
594 // fall-through ok!
595 case CONTROL_BLOCK:
596 disk = getDisk(channel);
597
598 if (disks[disk] == NULL)
599 break;
600
601 switch (offset) {
602 case DATA_OFFSET:
603 switch (req->size) {
604 case sizeof(uint16_t):
605 disks[disk]->write(offset, reg_type, data);
606 break;
607
608 case sizeof(uint32_t):
609 disks[disk]->write(offset, reg_type, data);
610 disks[disk]->write(offset, reg_type, &data[2]);
611 break;
612 default:
613 panic("IDE write of data reg invalid size: %#x\n", req->size);
614 }
615 break;
616 default:
617 if (req->size == sizeof(uint8_t)) {
618 disks[disk]->write(offset, reg_type, data);
619 } else
620 panic("IDE write of command reg of invalid size: %#x\n", req->size);
621 }
622 break;
623 default:
624 panic("IDE controller write of unknown register block type!\n");
625 }
626
627 DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
628 offset, req->size, *(uint32_t*)data);
629
630 return No_Fault;
631 }
632
633 ////
634 // Serialization
635 ////
636
637 void
638 IdeController::serialize(std::ostream &os)
639 {
640 // Serialize the PciDev base class
641 PciDev::serialize(os);
642
643 // Serialize register addresses and sizes
644 SERIALIZE_SCALAR(pri_cmd_addr);
645 SERIALIZE_SCALAR(pri_cmd_size);
646 SERIALIZE_SCALAR(pri_ctrl_addr);
647 SERIALIZE_SCALAR(pri_ctrl_size);
648 SERIALIZE_SCALAR(sec_cmd_addr);
649 SERIALIZE_SCALAR(sec_cmd_size);
650 SERIALIZE_SCALAR(sec_ctrl_addr);
651 SERIALIZE_SCALAR(sec_ctrl_size);
652 SERIALIZE_SCALAR(bmi_addr);
653 SERIALIZE_SCALAR(bmi_size);
654
655 // Serialize registers
656 SERIALIZE_ARRAY(bmi_regs.data,
657 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
658 SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
659 SERIALIZE_ARRAY(config_regs.data,
660 sizeof(config_regs.data) / sizeof(config_regs.data[0]));
661
662 // Serialize internal state
663 SERIALIZE_SCALAR(io_enabled);
664 SERIALIZE_SCALAR(bm_enabled);
665 SERIALIZE_ARRAY(cmd_in_progress,
666 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
667 }
668
669 void
670 IdeController::unserialize(Checkpoint *cp, const std::string &section)
671 {
672 // Unserialize the PciDev base class
673 PciDev::unserialize(cp, section);
674
675 // Unserialize register addresses and sizes
676 UNSERIALIZE_SCALAR(pri_cmd_addr);
677 UNSERIALIZE_SCALAR(pri_cmd_size);
678 UNSERIALIZE_SCALAR(pri_ctrl_addr);
679 UNSERIALIZE_SCALAR(pri_ctrl_size);
680 UNSERIALIZE_SCALAR(sec_cmd_addr);
681 UNSERIALIZE_SCALAR(sec_cmd_size);
682 UNSERIALIZE_SCALAR(sec_ctrl_addr);
683 UNSERIALIZE_SCALAR(sec_ctrl_size);
684 UNSERIALIZE_SCALAR(bmi_addr);
685 UNSERIALIZE_SCALAR(bmi_size);
686
687 // Unserialize registers
688 UNSERIALIZE_ARRAY(bmi_regs.data,
689 sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
690 UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
691 UNSERIALIZE_ARRAY(config_regs.data,
692 sizeof(config_regs.data) / sizeof(config_regs.data[0]));
693
694 // Unserialize internal state
695 UNSERIALIZE_SCALAR(io_enabled);
696 UNSERIALIZE_SCALAR(bm_enabled);
697 UNSERIALIZE_ARRAY(cmd_in_progress,
698 sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
699
700 if (pioInterface) {
701 pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size));
702 pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size));
703 pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size));
704 pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size));
705 pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
706 }
707 }
708
709 #ifndef DOXYGEN_SHOULD_SKIP_THIS
710
711 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
712
713 Param<Addr> addr;
714 SimObjectVectorParam<IdeDisk *> disks;
715 SimObjectParam<MemoryController *> mmu;
716 SimObjectParam<PciConfigAll *> configspace;
717 SimObjectParam<PciConfigData *> configdata;
718 SimObjectParam<Platform *> platform;
719 Param<uint32_t> pci_bus;
720 Param<uint32_t> pci_dev;
721 Param<uint32_t> pci_func;
722 SimObjectParam<Bus *> pio_bus;
723 SimObjectParam<Bus *> dma_bus;
724 Param<Tick> pio_latency;
725 SimObjectParam<HierParams *> hier;
726
727 END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
728
729 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
730
731 INIT_PARAM(addr, "Device Address"),
732 INIT_PARAM(disks, "IDE disks attached to this controller"),
733 INIT_PARAM(mmu, "Memory controller"),
734 INIT_PARAM(configspace, "PCI Configspace"),
735 INIT_PARAM(configdata, "PCI Config data"),
736 INIT_PARAM(platform, "Platform pointer"),
737 INIT_PARAM(pci_bus, "PCI bus ID"),
738 INIT_PARAM(pci_dev, "PCI device number"),
739 INIT_PARAM(pci_func, "PCI function code"),
740 INIT_PARAM(pio_bus, ""),
741 INIT_PARAM(dma_bus, ""),
742 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
743 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
744
745 END_INIT_SIM_OBJECT_PARAMS(IdeController)
746
747 CREATE_SIM_OBJECT(IdeController)
748 {
749 IdeController::Params *params = new IdeController::Params;
750 params->name = getInstanceName();
751 params->mmu = mmu;
752 params->configSpace = configspace;
753 params->configData = configdata;
754 params->plat = platform;
755 params->busNum = pci_bus;
756 params->deviceNum = pci_dev;
757 params->functionNum = pci_func;
758
759 params->disks = disks;
760 params->pio_bus = pio_bus;
761 params->dma_bus = dma_bus;
762 params->pio_latency = pio_latency;
763 params->hier = hier;
764 return new IdeController(params);
765 }
766
767 REGISTER_SIM_OBJECT("IdeController", IdeController)
768
769 #endif //DOXYGEN_SHOULD_SKIP_THIS