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