2 * Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
30 * Device model implementation for an IDE disk
38 #include "arch/alpha/pmap.h"
39 #include "base/cprintf.hh" // csprintf
40 #include "base/trace.hh"
41 #include "dev/disk_image.hh"
42 #include "dev/ide_disk.hh"
43 #include "dev/ide_ctrl.hh"
44 #include "dev/tsunami.hh"
45 #include "dev/tsunami_pchip.hh"
46 #include "mem/functional_mem/physical_memory.hh"
47 #include "mem/bus/bus.hh"
48 #include "mem/bus/dma_interface.hh"
49 #include "mem/bus/pio_interface.hh"
50 #include "mem/bus/pio_interface_impl.hh"
51 #include "sim/builder.hh"
52 #include "sim/sim_object.hh"
53 #include "sim/universe.hh"
57 IdeDisk::IdeDisk(const string
&name
, DiskImage
*img
, PhysicalMemory
*phys
,
59 : SimObject(name
), ctrl(NULL
), image(img
), physmem(phys
),
60 dmaTransferEvent(this), dmaReadWaitEvent(this),
61 dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
62 dmaReadEvent(this), dmaWriteEvent(this)
64 diskDelay
= (delay
* ticksPerSecond
/ 100000);
66 // initialize the data buffer and shadow registers
67 dataBuffer
= new uint8_t[MAX_DMA_SIZE
];
69 memset(dataBuffer
, 0, MAX_DMA_SIZE
);
70 memset(&cmdReg
, 0, sizeof(CommandReg_t
));
71 memset(&curPrd
.entry
, 0, sizeof(PrdEntry_t
));
81 // fill out the drive ID structure
82 memset(&driveID
, 0, sizeof(struct hd_driveid
));
84 // Calculate LBA and C/H/S values
89 uint32_t lba_size
= image
->size();
90 if (lba_size
>= 16383*16*63) {
100 if ((lba_size
/ sectors
) >= 16)
103 heads
= (lba_size
/ sectors
);
105 cylinders
= lba_size
/ (heads
* sectors
);
108 // Setup the model name
109 sprintf((char *)driveID
.model
, "5MI EDD si k");
110 // Set the maximum multisector transfer size
111 driveID
.max_multsect
= MAX_MULTSECT
;
112 // IORDY supported, IORDY disabled, LBA enabled, DMA enabled
113 driveID
.capability
= 0x7;
114 // UDMA support, EIDE support
115 driveID
.field_valid
= 0x6;
116 // Setup default C/H/S settings
117 driveID
.cyls
= cylinders
;
118 driveID
.sectors
= sectors
;
119 driveID
.heads
= heads
;
120 // Setup the current multisector transfer size
121 driveID
.multsect
= MAX_MULTSECT
;
122 driveID
.multsect_valid
= 0x1;
123 // Number of sectors on disk
124 driveID
.lba_capacity
= lba_size
;
125 // Multiword DMA mode 2 and below supported
126 driveID
.dma_mword
= 0x400;
127 // Set PIO mode 4 and 3 supported
128 driveID
.eide_pio_modes
= 0x3;
129 // Set DMA mode 4 and below supported
130 driveID
.dma_ultra
= 0x10;
131 // Statically set hardware config word
132 driveID
.hw_config
= 0x4001;
134 // set the device state to idle
138 devState
= Device_Idle_S
;
140 } else if (id
== DEV1
) {
141 devState
= Device_Idle_NS
;
144 panic("Invalid device ID: %#x\n", id
);
147 // set the device ready bit
148 cmdReg
.status
|= STATUS_DRDY_BIT
;
153 // destroy the data buffer
154 delete [] dataBuffer
;
158 IdeDisk::pciToDma(Addr
&pciAddr
)
161 return ctrl
->tsunami
->pchip
->translatePciToDma(pciAddr
);
163 panic("Access to unset controller!\n");
167 // Device registers read/write
171 IdeDisk::read(const Addr
&offset
, bool byte
, bool cmdBlk
, uint8_t *data
)
173 DevAction_t action
= ACT_NONE
;
176 if (offset
< 0 || offset
> sizeof(CommandReg_t
))
177 panic("Invalid disk command register offset: %#x\n", offset
);
179 if (!byte
&& offset
!= DATA_OFFSET
)
180 panic("Invalid 16-bit read, only allowed on data reg\n");
183 *(uint16_t *)data
= *(uint16_t *)&cmdReg
.data0
;
185 *data
= ((uint8_t *)&cmdReg
)[offset
];
187 // determine if an action needs to be taken on the state machine
188 if (offset
== STATUS_OFFSET
) {
189 action
= ACT_STAT_READ
;
190 } else if (offset
== DATA_OFFSET
) {
192 action
= ACT_DATA_READ_BYTE
;
194 action
= ACT_DATA_READ_SHORT
;
198 if (offset
!= ALTSTAT_OFFSET
)
199 panic("Invalid disk control register offset: %#x\n", offset
);
202 panic("Invalid 16-bit read from control block\n");
204 *data
= ((uint8_t *)&cmdReg
)[STATUS_OFFSET
];
207 if (action
!= ACT_NONE
)
212 IdeDisk::write(const Addr
&offset
, bool byte
, bool cmdBlk
, const uint8_t *data
)
214 DevAction_t action
= ACT_NONE
;
217 if (offset
< 0 || offset
> sizeof(CommandReg_t
))
218 panic("Invalid disk command register offset: %#x\n", offset
);
220 if (!byte
&& offset
!= DATA_OFFSET
)
221 panic("Invalid 16-bit write, only allowed on data reg\n");
224 *((uint16_t *)&cmdReg
.data0
) = *(uint16_t *)data
;
226 ((uint8_t *)&cmdReg
)[offset
] = *data
;
228 // determine if an action needs to be taken on the state machine
229 if (offset
== COMMAND_OFFSET
) {
230 action
= ACT_CMD_WRITE
;
231 } else if (offset
== DATA_OFFSET
) {
233 action
= ACT_DATA_WRITE_BYTE
;
235 action
= ACT_DATA_WRITE_SHORT
;
239 if (offset
!= CONTROL_OFFSET
)
240 panic("Invalid disk control register offset: %#x\n", offset
);
243 panic("Invalid 16-bit write to control block\n");
245 if (*data
& CONTROL_RST_BIT
)
246 panic("Software reset not supported!\n");
248 nIENBit
= (*data
& CONTROL_IEN_BIT
) ? true : false;
251 if (action
!= ACT_NONE
)
256 // Perform DMA transactions
260 IdeDisk::doDmaTransfer()
262 if (dmaState
!= Dma_Transfer
|| devState
!= Transfer_Data_Dma
)
263 panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
266 // first read the current PRD
268 if (dmaInterface
->busy()) {
269 // reschedule after waiting period
270 dmaTransferEvent
.schedule(curTick
+ DMA_BACKOFF_PERIOD
);
274 dmaInterface
->doDMA(Read
, curPrdAddr
, sizeof(PrdEntry_t
), curTick
,
282 IdeDisk::dmaPrdReadDone()
284 // actually copy the PRD from physical memory
285 memcpy((void *)&curPrd
.entry
,
286 physmem
->dma_addr(curPrdAddr
, sizeof(PrdEntry_t
)),
289 curPrdAddr
+= sizeof(PrdEntry_t
);
300 Tick totalDiskDelay
= diskDelay
* (curPrd
.getByteCount() / SectorSize
);
303 if (dmaInterface
->busy()) {
304 // reschedule after waiting period
305 dmaReadWaitEvent
.schedule(curTick
+ DMA_BACKOFF_PERIOD
);
310 ctrl
->tsunami
->pchip
->translatePciToDma(curPrd
.getBaseAddr());
311 dmaInterface
->doDMA(Read
, dmaAddr
, curPrd
.getByteCount(),
312 curTick
+ totalDiskDelay
, &dmaReadEvent
);
314 // schedule dmaReadEvent with sectorDelay (dmaReadDone)
315 dmaReadEvent
.schedule(curTick
+ totalDiskDelay
);
320 IdeDisk::dmaReadDone()
323 Addr curAddr
= 0, dmaAddr
= 0;
324 uint32_t bytesWritten
= 0, bytesInPage
= 0, bytesLeft
= 0;
326 // set initial address
327 curAddr
= curPrd
.getBaseAddr();
329 // clear out the data buffer
330 memset(dataBuffer
, 0, MAX_DMA_SIZE
);
332 // read the data from memory via DMA into a data buffer
333 while (bytesWritten
< curPrd
.getByteCount()) {
334 if (cmdBytesLeft
<= 0)
335 panic("DMA data is larger than # of sectors specified\n");
337 dmaAddr
= pciToDma(curAddr
);
339 // calculate how many bytes are in the current page
340 bytesLeft
= curPrd
.getByteCount() - bytesWritten
;
341 bytesInPage
= (bytesLeft
> ALPHA_PGBYTES
) ? ALPHA_PGBYTES
: bytesLeft
;
342 // check to make sure we don't cross a page boundary
343 if ((curAddr
+ bytesInPage
) >
344 (alpha_trunc_page(curAddr
) + ALPHA_PGBYTES
))
346 bytesInPage
= alpha_round_page(curAddr
) - curAddr
;
348 // copy the data from memory into the data buffer
349 /** @todo Use real DMA with interfaces here */
350 memcpy((void *)(dataBuffer
+ bytesWritten
),
351 physmem
->dma_addr(dmaAddr
, bytesInPage
),
354 curAddr
+= bytesInPage
;
355 bytesWritten
+= bytesInPage
;
356 cmdBytesLeft
-= bytesInPage
;
359 // write the data to the disk image
360 for (bytesWritten
= 0;
361 bytesWritten
< curPrd
.getByteCount();
362 bytesWritten
+= SectorSize
)
364 writeDisk(curSector
++, (uint8_t *)(dataBuffer
+ bytesWritten
));
367 // actually copy the data from memory to data buffer
369 ctrl
->tsunami
->pchip
->translatePciToDma(curPrd
.getBaseAddr());
370 memcpy((void *)dataBuffer
,
371 physmem
->dma_addr(dmaAddr
, curPrd
.getByteCount()),
372 curPrd
.getByteCount());
374 uint32_t bytesWritten
= 0;
376 while (bytesWritten
< curPrd
.getByteCount()) {
377 if (cmdBytesLeft
<= 0)
378 panic("DMA data is larger than # sectors specified\n");
380 writeDisk(curSector
++, (uint8_t *)(dataBuffer
+ bytesWritten
));
382 bytesWritten
+= SectorSize
;
383 cmdBytesLeft
-= SectorSize
;
388 if (curPrd
.getEOT()){
389 assert(cmdBytesLeft
== 0);
391 updateState(ACT_DMA_DONE
);
398 IdeDisk::doDmaWrite()
400 Tick totalDiskDelay
= diskDelay
* (curPrd
.getByteCount() / SectorSize
);
403 if (dmaInterface
->busy()) {
404 // reschedule after waiting period
405 dmaWriteWaitEvent
.schedule(curTick
+ DMA_BACKOFF_PERIOD
);
410 ctrl
->tsunami
->pchip
->translatePciToDma(curPrd
.getBaseAddr());
411 dmaInterface
->doDMA(WriteInvalidate
, dmaAddr
,
412 curPrd
.getByteCount(), curTick
+ totalDiskDelay
,
415 // schedule event with disk delay (dmaWriteDone)
416 dmaWriteEvent
.schedule(curTick
+ totalDiskDelay
);
421 IdeDisk::dmaWriteDone()
423 Addr curAddr
= 0, pageAddr
= 0, dmaAddr
= 0;
424 uint32_t bytesRead
= 0, bytesInPage
= 0;
426 // setup the initial page and DMA address
427 curAddr
= curPrd
.getBaseAddr();
428 pageAddr
= alpha_trunc_page(curAddr
);
429 dmaAddr
= pciToDma(curAddr
);
431 // clear out the data buffer
432 memset(dataBuffer
, 0, MAX_DMA_SIZE
);
434 while (bytesRead
< curPrd
.getByteCount()) {
435 // see if we have crossed into a new page
436 if (pageAddr
!= alpha_trunc_page(curAddr
)) {
437 // write the data to memory
438 /** @todo Do real DMA using interfaces here */
439 memcpy(physmem
->dma_addr(dmaAddr
, bytesInPage
),
440 (void *)(dataBuffer
+ (bytesRead
- bytesInPage
)),
443 // update the DMA address and page address
444 pageAddr
= alpha_trunc_page(curAddr
);
445 dmaAddr
= pciToDma(curAddr
);
450 if (cmdBytesLeft
<= 0)
451 panic("DMA requested data is larger than # sectors specified\n");
453 readDisk(curSector
++, (uint8_t *)(dataBuffer
+ bytesRead
));
455 curAddr
+= SectorSize
;
456 bytesRead
+= SectorSize
;
457 bytesInPage
+= SectorSize
;
458 cmdBytesLeft
-= SectorSize
;
461 // write the last page worth read to memory
462 /** @todo Do real DMA using interfaces here */
463 if (bytesInPage
!= 0) {
464 memcpy(physmem
->dma_addr(dmaAddr
, bytesInPage
),
465 (void *)(dataBuffer
+ (bytesRead
- bytesInPage
)),
470 Addr dmaAddr
= ctrl
->tsunami
->pchip
->
471 translatePciToDma(curPrd
.getBaseAddr());
473 memcpy(physmem
->dma_addr(dmaAddr
, curPrd
.getByteCount()),
474 (void *)dataBuffer
, curPrd
.getByteCount());
478 if (curPrd
.getEOT()) {
479 assert(cmdBytesLeft
== 0);
481 updateState(ACT_DMA_DONE
);
488 // Disk utility routines
492 IdeDisk::readDisk(uint32_t sector
, uint8_t *data
)
494 uint32_t bytesRead
= image
->read(data
, sector
);
496 if (bytesRead
!= SectorSize
)
497 panic("Can't read from %s. Only %d of %d read. errno=%d\n",
498 name(), bytesRead
, SectorSize
, errno
);
502 IdeDisk::writeDisk(uint32_t sector
, uint8_t *data
)
504 uint32_t bytesWritten
= image
->write(data
, sector
);
506 if (bytesWritten
!= SectorSize
)
507 panic("Can't write to %s. Only %d of %d written. errno=%d\n",
508 name(), bytesWritten
, SectorSize
, errno
);
512 // Setup and handle commands
516 IdeDisk::startDma(const uint32_t &prdTableBase
)
518 if (dmaState
!= Dma_Start
)
519 panic("Inconsistent DMA state, should be in Dma_Start!\n");
521 if (devState
!= Transfer_Data_Dma
)
522 panic("Inconsistent device state for DMA start!\n");
524 curPrdAddr
= ctrl
->tsunami
->pchip
->translatePciToDma(prdTableBase
);
526 dmaState
= Dma_Transfer
;
528 // schedule dma transfer (doDmaTransfer)
529 dmaTransferEvent
.schedule(curTick
+ 1);
535 if (dmaState
== Dma_Idle
)
536 panic("Inconsistent DMA state, should be in Dma_Start or Dma_Transfer!\n");
538 if (devState
!= Transfer_Data_Dma
&& devState
!= Prepare_Data_Dma
)
539 panic("Inconsistent device state, should be in Transfer or Prepare!\n");
541 updateState(ACT_CMD_ERROR
);
545 IdeDisk::startCommand()
547 DevAction_t action
= ACT_NONE
;
551 // copy the command to the shadow
552 curCommand
= cmdReg
.command
;
555 switch (cmdReg
.command
) {
556 // Supported non-data commands
557 case WIN_READ_NATIVE_MAX
:
558 size
= image
->size() - 1;
559 cmdReg
.sec_num
= (size
& 0xff);
560 cmdReg
.cyl_low
= ((size
& 0xff00) >> 8);
561 cmdReg
.cyl_high
= ((size
& 0xff0000) >> 16);
562 cmdReg
.head
= ((size
& 0xf000000) >> 24);
564 devState
= Command_Execution
;
565 action
= ACT_CMD_COMPLETE
;
570 case WIN_FLUSH_CACHE
:
573 case WIN_SETFEATURES
:
575 devState
= Command_Execution
;
576 action
= ACT_CMD_COMPLETE
;
579 // Supported PIO data-in commands
581 cmdBytesLeft
= drqBytesLeft
= sizeof(struct hd_driveid
);
582 devState
= Prepare_Data_In
;
583 action
= ACT_DATA_READY
;
588 if (!(cmdReg
.drive
& DRIVE_LBA_BIT
))
589 panic("Attempt to perform CHS access, only supports LBA\n");
591 if (cmdReg
.sec_count
== 0)
592 cmdBytesLeft
= (256 * SectorSize
);
594 cmdBytesLeft
= (cmdReg
.sec_count
* SectorSize
);
596 drqBytesLeft
= SectorSize
;
597 curSector
= getLBABase();
599 devState
= Prepare_Data_In
;
600 action
= ACT_DATA_READY
;
603 // Supported PIO data-out commands
606 if (!(cmdReg
.drive
& DRIVE_LBA_BIT
))
607 panic("Attempt to perform CHS access, only supports LBA\n");
609 if (cmdReg
.sec_count
== 0)
610 cmdBytesLeft
= (256 * SectorSize
);
612 cmdBytesLeft
= (cmdReg
.sec_count
* SectorSize
);
614 drqBytesLeft
= SectorSize
;
615 curSector
= getLBABase();
617 devState
= Prepare_Data_Out
;
618 action
= ACT_DATA_READY
;
621 // Supported DMA commands
623 dmaRead
= true; // a write to the disk is a DMA read from memory
625 if (!(cmdReg
.drive
& DRIVE_LBA_BIT
))
626 panic("Attempt to perform CHS access, only supports LBA\n");
628 if (cmdReg
.sec_count
== 0)
629 cmdBytesLeft
= (256 * SectorSize
);
631 cmdBytesLeft
= (cmdReg
.sec_count
* SectorSize
);
633 drqBytesLeft
= SectorSize
;
634 curSector
= getLBABase();
636 devState
= Prepare_Data_Dma
;
637 action
= ACT_DMA_READY
;
641 panic("Unsupported ATA command: %#x\n", cmdReg
.command
);
644 if (action
!= ACT_NONE
) {
646 cmdReg
.status
|= STATUS_BSY_BIT
;
648 cmdReg
.status
&= ~STATUS_DRQ_BIT
;
655 // Handle setting and clearing interrupts
662 panic("Attempt to post an interrupt with one pending\n");
666 // talk to controller to set interrupt
675 panic("Attempt to clear a non-pending interrupt\n");
679 // talk to controller to clear interrupt
685 // Manage the device internal state machine
689 IdeDisk::updateState(DevAction_t action
)
694 devState
= Device_Idle_NS
;
695 else if (action
== ACT_CMD_WRITE
)
701 if (!isDEVSelect()) {
702 devState
= Device_Idle_NS
;
704 } else if (action
== ACT_STAT_READ
|| isIENSet()) {
705 devState
= Device_Idle_S
;
707 } else if (action
== ACT_CMD_WRITE
) {
716 if (!isIENSet() && intrPending
) {
717 devState
= Device_Idle_SI
;
720 if (isIENSet() || !intrPending
) {
721 devState
= Device_Idle_S
;
726 case Command_Execution
:
727 if (action
== ACT_CMD_COMPLETE
) {
732 devState
= Device_Idle_SI
;
735 devState
= Device_Idle_S
;
740 case Prepare_Data_In
:
741 if (action
== ACT_CMD_ERROR
) {
746 devState
= Device_Idle_SI
;
749 devState
= Device_Idle_S
;
751 } else if (action
== ACT_DATA_READY
) {
753 cmdReg
.status
&= ~STATUS_BSY_BIT
;
755 cmdReg
.status
|= STATUS_DRQ_BIT
;
757 // put the first two bytes into the data register
758 memcpy((void *)&cmdReg
.data0
, (void *)dataBuffer
,
761 // copy the data into the data buffer
762 if (curCommand
== WIN_IDENTIFY
)
763 memcpy((void *)dataBuffer
, (void *)&driveID
,
764 sizeof(struct hd_driveid
));
766 readDisk(curSector
++, dataBuffer
);
769 devState
= Data_Ready_INTRQ_In
;
772 devState
= Transfer_Data_In
;
777 case Data_Ready_INTRQ_In
:
778 if (action
== ACT_STAT_READ
) {
779 devState
= Transfer_Data_In
;
784 case Transfer_Data_In
:
785 if (action
== ACT_DATA_READ_BYTE
|| action
== ACT_DATA_READ_SHORT
) {
786 if (action
== ACT_DATA_READ_BYTE
) {
787 panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");
792 // copy next short into data registers
793 memcpy((void *)&cmdReg
.data0
,
794 (void *)&dataBuffer
[SectorSize
- drqBytesLeft
],
798 if (drqBytesLeft
== 0) {
799 if (cmdBytesLeft
== 0) {
802 devState
= Device_Idle_S
;
804 devState
= Prepare_Data_In
;
805 cmdReg
.status
|= STATUS_BSY_BIT
;
811 case Prepare_Data_Out
:
812 if (action
== ACT_CMD_ERROR
|| cmdBytesLeft
== 0) {
817 devState
= Device_Idle_SI
;
820 devState
= Device_Idle_S
;
822 } else if (cmdBytesLeft
!= 0) {
824 cmdReg
.status
&= ~STATUS_BSY_BIT
;
826 cmdReg
.status
|= STATUS_DRQ_BIT
;
828 // clear the data buffer to get it ready for writes
829 memset(dataBuffer
, 0, MAX_DMA_SIZE
);
832 devState
= Data_Ready_INTRQ_Out
;
835 devState
= Transfer_Data_Out
;
840 case Data_Ready_INTRQ_Out
:
841 if (action
== ACT_STAT_READ
) {
842 devState
= Transfer_Data_Out
;
847 case Transfer_Data_Out
:
848 if (action
== ACT_DATA_WRITE_BYTE
||
849 action
== ACT_DATA_WRITE_SHORT
) {
851 if (action
== ACT_DATA_READ_BYTE
) {
852 panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
854 // copy the latest short into the data buffer
855 memcpy((void *)&dataBuffer
[SectorSize
- drqBytesLeft
],
856 (void *)&cmdReg
.data0
,
863 if (drqBytesLeft
== 0) {
864 // copy the block to the disk
865 writeDisk(curSector
++, dataBuffer
);
868 cmdReg
.status
|= STATUS_BSY_BIT
;
870 cmdReg
.status
&= ~STATUS_DRQ_BIT
;
872 devState
= Prepare_Data_Out
;
877 case Prepare_Data_Dma
:
878 if (action
== ACT_CMD_ERROR
) {
883 devState
= Device_Idle_SI
;
886 devState
= Device_Idle_S
;
888 } else if (action
== ACT_DMA_READY
) {
890 cmdReg
.status
&= ~STATUS_BSY_BIT
;
892 cmdReg
.status
|= STATUS_DRQ_BIT
;
894 devState
= Transfer_Data_Dma
;
896 if (dmaState
!= Dma_Idle
)
897 panic("Inconsistent DMA state, should be Dma_Idle\n");
899 dmaState
= Dma_Start
;
900 // wait for the write to the DMA start bit
904 case Transfer_Data_Dma
:
905 if (action
== ACT_CMD_ERROR
|| action
== ACT_DMA_DONE
) {
909 cmdReg
.status
|= 0x10;
910 // clear the controller state for DMA transfer
911 ctrl
->setDmaComplete(this);
914 devState
= Device_Idle_SI
;
917 devState
= Device_Idle_S
;
923 panic("Unknown IDE device state: %#x\n", devState
);
928 IdeDisk::serialize(ostream
&os
)
933 IdeDisk::unserialize(Checkpoint
*cp
, const string
§ion
)
937 #ifndef DOXYGEN_SHOULD_SKIP_THIS
939 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk
)
941 SimObjectParam
<DiskImage
*> image
;
942 SimObjectParam
<PhysicalMemory
*> physmem
;
944 Param
<int> disk_delay
;
946 END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk
)
948 BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk
)
950 INIT_PARAM(image
, "Disk image"),
951 INIT_PARAM(physmem
, "Physical memory"),
952 INIT_PARAM(driveID
, "Drive ID (0=master 1=slave)"),
953 INIT_PARAM_DFLT(disk_delay
, "Fixed disk delay in milliseconds", 0)
955 END_INIT_SIM_OBJECT_PARAMS(IdeDisk
)
958 CREATE_SIM_OBJECT(IdeDisk
)
960 return new IdeDisk(getInstanceName(), image
, physmem
, driveID
,
964 REGISTER_SIM_OBJECT("IdeDisk", IdeDisk
)
966 #endif //DOXYGEN_SHOULD_SKIP_THIS