2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Copyright 2008, Marcus Overhagen.
4 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
5 * Copyright 2002-2003, Thomas Kurschel.
7 * Distributed under the terms of the MIT License.
10 #include "ATAPrivate.h"
13 ATAChannel::ATAChannel(device_node
*node
)
19 fExpectsInterrupt(false),
27 B_INITIALIZE_SPINLOCK(&fInterruptLock
);
28 fInterruptCondition
.Init(this, "ata dma transfer");
30 gDeviceManager
->get_attr_uint32(node
, ATA_CHANNEL_ID_ITEM
, &fChannelID
,
32 snprintf(fDebugContext
, sizeof(fDebugContext
), " %lu", fChannelID
);
35 void *settings
= load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS
);
36 if (settings
!= NULL
) {
37 if (get_driver_boolean_parameter(settings
,
38 B_SAFEMODE_DISABLE_IDE_DMA
, false, false)) {
39 TRACE_ALWAYS("disabling DMA because of safemode setting\n");
43 unload_driver_settings(settings
);
49 if (gDeviceManager
->get_attr_uint8(node
, ATA_CONTROLLER_CAN_DMA_ITEM
,
50 &canDMA
, true) != B_OK
) {
51 TRACE_ERROR("unknown if controller supports DMA, not using it\n");
56 TRACE_ALWAYS("controller doesn't support DMA, disabling\n");
61 fRequest
= new(std::nothrow
) ATARequest(true);
62 if (fRequest
== NULL
) {
63 fStatus
= B_NO_MEMORY
;
68 if (gDeviceManager
->get_attr_uint8(node
, ATA_CONTROLLER_MAX_DEVICES_ITEM
,
69 &maxDevices
, true) != B_OK
) {
73 fDeviceCount
= MIN(maxDevices
, 2);
74 fDevices
= new(std::nothrow
) ATADevice
*[fDeviceCount
];
75 if (fDevices
== NULL
) {
76 fStatus
= B_NO_MEMORY
;
80 for (uint8 i
= 0; i
< fDeviceCount
; i
++)
83 device_node
*parent
= gDeviceManager
->get_parent_node(node
);
84 fStatus
= gDeviceManager
->get_driver(parent
,
85 (driver_module_info
**)&fController
, &fCookie
);
86 gDeviceManager
->put_node(parent
);
88 fController
->set_channel(fCookie
, this);
92 ATAChannel::~ATAChannel()
95 for (uint8 i
= 0; i
< fDeviceCount
; i
++)
105 ATAChannel::InitCheck()
112 ATAChannel::SetBus(scsi_bus bus
)
119 ATAChannel::_DevicePresent(int device
)
121 SelectDevice(device
);
123 if (SelectedDevice() != device
) {
124 TRACE_ALWAYS("_DevicePresent: device selection failed for device %i\n",
129 ata_task_file taskFile
;
130 taskFile
.chs
.sector_count
= 0x5a;
131 taskFile
.chs
.sector_number
= 0xa5;
132 if (_WriteRegs(&taskFile
, ATA_MASK_SECTOR_COUNT
133 | ATA_MASK_SECTOR_NUMBER
) != B_OK
) {
134 TRACE_ERROR("_DevicePresent: writing registers failed\n");
137 if (_ReadRegs(&taskFile
, ATA_MASK_SECTOR_COUNT
138 | ATA_MASK_SECTOR_NUMBER
) != B_OK
) {
139 TRACE_ERROR("_DevicePresent: reading registers failed\n");
142 bool present
= (taskFile
.chs
.sector_count
== 0x5a &&
143 taskFile
.chs
.sector_number
== 0xa5);
145 TRACE_ALWAYS("_DevicePresent: device %i, presence %d\n", device
, present
);
151 ATAChannel::ScanBus()
155 for (int i
= 0; i
< fDeviceCount
; i
++)
156 deviceMask
|= (int)_DevicePresent(i
) << i
;
158 status_t result
= Reset();
159 if (result
!= B_OK
) {
160 TRACE_ERROR("resetting the channel failed\n");
164 TRACE_ALWAYS("deviceMask %d\n", deviceMask
);
166 for (int i
= 0; i
< fDeviceCount
; i
++) {
167 if (!(deviceMask
& (1 << i
))) {
168 TRACE_ALWAYS("ignoring device %d\n", i
);
172 TRACE_ALWAYS("probing device %d\n", i
);
175 // ensure interrupts are disabled for this device
176 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
178 // wait up to 3 seconds for busy to clear
179 if (Wait(0, ATA_STATUS_BUSY
, 0, 3 * 1000 * 1000) != B_OK
) {
180 uint8 status
= AltStatus();
181 if (status
== 0xff || status
== 0x7f) {
182 TRACE_ALWAYS("illegal status value 0x%02x for device %d\n",
186 TRACE_ALWAYS("device %d is slow\n", i
);
190 // wait up to 31 seconds for busy to clear (already 3 sec. waited)
191 if (Wait(0, ATA_STATUS_BUSY
, 0, 28 * 1000 * 1000) != B_OK
) {
192 TRACE_ALWAYS("device %d reset timeout\n", i
);
200 if (SelectedDevice() != i
) {
201 TRACE_ALWAYS("device selection failed for device %i\n", i
);
205 ata_task_file taskFile
;
206 if (_ReadRegs(&taskFile
, ATA_MASK_LBA_MID
| ATA_MASK_LBA_HIGH
207 | ATA_MASK_ERROR
) != B_OK
) {
208 TRACE_ERROR("reading status failed\n");
212 // for information only
213 if ((i
== 0) && (taskFile
.read
.error
& 0x80)) {
214 TRACE_ERROR("device 0 indicates that device 1 failed"
215 " error code is 0x%02x\n", taskFile
.read
.error
);
216 } else if (taskFile
.read
.error
!= 0x01) {
217 TRACE_ERROR("device %d failed, error code is 0x%02x\n",
218 i
, taskFile
.read
.error
);
221 uint16 signature
= taskFile
.lba
.lba_8_15
222 | (((uint16
)taskFile
.lba
.lba_16_23
) << 8);
223 TRACE_ALWAYS("signature of device %d: 0x%04x\n", i
, signature
);
225 ATADevice
*device
= NULL
;
226 if (signature
== ATA_SIGNATURE_ATAPI
)
227 device
= new(std::nothrow
) ATAPIDevice(this, i
);
229 device
= new(std::nothrow
) ATADevice(this, i
);
231 if (device
== NULL
) {
232 TRACE_ERROR("out of memory allocating device\n");
236 TRACE("trying ATA%s device %u\n", device
->IsATAPI() ? "PI" : "", i
);
238 if (device
->Identify() != B_OK
) {
243 if (device
->Configure() != B_OK
) {
244 TRACE_ERROR("failed to configure device\n");
249 TRACE_ALWAYS("identified ATA%s device %u\n", device
->IsATAPI()
252 fDevices
[i
] = device
;
260 ATAChannel::PathInquiry(scsi_path_inquiry
*info
)
262 info
->hba_inquiry
= SCSI_PI_TAG_ABLE
| SCSI_PI_WIDE_16
;
265 info
->initiator_id
= 2;
266 info
->hba_queue_size
= 1;
267 memset(info
->vuhba_flags
, 0, sizeof(info
->vuhba_flags
));
269 strlcpy(info
->sim_vid
, "Haiku", SCSI_SIM_ID
);
271 const char *controllerName
= NULL
;
272 if (gDeviceManager
->get_attr_string(fNode
,
273 SCSI_DESCRIPTION_CONTROLLER_NAME
, &controllerName
, true) == B_OK
)
274 strlcpy(info
->hba_vid
, controllerName
, SCSI_HBA_ID
);
276 strlcpy(info
->hba_vid
, "unknown", SCSI_HBA_ID
);
278 strlcpy(info
->sim_version
, "1.0", SCSI_VERS
);
279 strlcpy(info
->hba_version
, "1.0", SCSI_VERS
);
280 strlcpy(info
->controller_family
, "ATA", SCSI_FAM_ID
);
281 strlcpy(info
->controller_type
, "ATA", SCSI_TYPE_ID
);
286 ATAChannel::GetRestrictions(uint8 targetID
, bool *isATAPI
, bool *noAutoSense
,
289 // we always indicate ATAPI so we have to emulate fewer commands
291 *noAutoSense
= false;
294 if (targetID
< fDeviceCount
&& fDevices
[targetID
] != NULL
)
295 fDevices
[targetID
]->GetRestrictions(noAutoSense
, maxBlocks
);
300 ATAChannel::ExecuteIO(scsi_ccb
*ccb
)
302 TRACE_FUNCTION("%p\n", ccb
);
303 status_t result
= fRequest
->Start(ccb
);
307 if (ccb
->cdb
[0] == SCSI_OP_REQUEST_SENSE
&& fRequest
->HasSense()) {
308 TRACE("request sense\n");
309 fRequest
->RequestSense();
310 fRequest
->Finish(false);
314 // we aren't a check sense request, clear sense data for new request
315 fRequest
->ClearSense();
317 if (ccb
->target_id
>= fDeviceCount
) {
318 TRACE_ERROR("invalid target device\n");
319 fRequest
->SetStatus(SCSI_SEL_TIMEOUT
);
320 fRequest
->Finish(false);
324 ATADevice
*device
= fDevices
[ccb
->target_id
];
325 if (device
== NULL
) {
326 TRACE_ERROR("target device not present\n");
327 fRequest
->SetStatus(SCSI_SEL_TIMEOUT
);
328 fRequest
->Finish(false);
332 fRequest
->SetTimeout(ccb
->timeout
> 0 ? ccb
->timeout
* 1000 * 1000
333 : ATA_STANDARD_TIMEOUT
);
335 result
= device
->ExecuteIO(fRequest
);
336 fRequest
->Finish(false);
342 ATAChannel::Control(uint8 targetID
, uint32 opcode
, void *buffer
, size_t length
)
344 if (targetID
< fDeviceCount
&& fDevices
[targetID
] != NULL
)
345 return fDevices
[targetID
]->Control(opcode
, buffer
, length
);
352 ATAChannel::SelectDevice(uint8 device
)
354 TRACE_FUNCTION("device: %u\n", device
);
359 ata_task_file taskFile
;
360 taskFile
.lba
.lba_24_27
= 0;
361 taskFile
.lba
.mode
= ATA_MODE_LBA
;
362 taskFile
.lba
.device
= device
;
364 status_t result
= _WriteRegs(&taskFile
, ATA_MASK_DEVICE_HEAD
);
365 if (result
!= B_OK
) {
366 TRACE_ERROR("writing register failed when trying to select device %d\n",
378 ATAChannel::SelectedDevice()
380 ata_task_file taskFile
;
381 if (_ReadRegs(&taskFile
, ATA_MASK_DEVICE_HEAD
) != B_OK
) {
382 TRACE_ERROR("reading register failed when detecting selected device\n");
383 // Return an invalid device number so that the
384 // SelectedDevice() == "expected device" check fails.
385 // Due to the device number being a bit, we can't really get values
386 // other than 0 and 1, so anything >= 2 can be regarded as invalid.
390 return taskFile
.lba
.device
;
397 TRACE_FUNCTION("\n");
401 // disable interrupts and assert SRST for at least 5 usec
402 if (_WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
403 | ATA_DEVICE_CONTROL_SOFT_RESET
) != B_OK
) {
404 TRACE_ERROR("failed to set reset signaling\n");
410 // clear reset and wait for at least 2 ms (wait 150ms like everyone else)
411 if (_WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
) != B_OK
) {
412 TRACE_ERROR("failed to clear reset signaling\n");
416 _FlushAndWait(150 * 1000);
418 // read status to clear any pending interrupts
426 ATAChannel::Wait(uint8 setBits
, uint8 clearedBits
, uint32 flags
,
429 bigtime_t startTime
= system_time();
432 TRACE("wait for set bits 0x%02x and cleared bits 0x%02x\n",
433 setBits
, clearedBits
);
436 unsigned lastStatus
= 0x100;
439 uint8 status
= AltStatus();
440 if ((flags
& ATA_CHECK_ERROR_BIT
) != 0
441 && (status
& ATA_STATUS_BUSY
) == 0
442 && (status
& ATA_STATUS_ERROR
) != 0) {
443 TRACE("wait failed, error bit set, status 0x%02x\n", status
);
447 if ((flags
& ATA_CHECK_DEVICE_FAULT
) != 0
448 && (status
& ATA_STATUS_BUSY
) == 0
449 && (status
& ATA_STATUS_DEVICE_FAULT
) != 0) {
450 TRACE("wait failed, device fault bit set, status 0x%02x\n", status
);
454 if ((status
& clearedBits
) == 0) {
455 if ((flags
& ATA_WAIT_ANY_BIT
) != 0 && (status
& setBits
) != 0) {
456 TRACE("wait success, status 0x%02x\n", status
);
459 if ((status
& setBits
) == setBits
) {
460 TRACE("wait success, status 0x%02x\n", status
);
465 bigtime_t elapsedTime
= system_time() - startTime
;
467 if (lastStatus
!= status
) {
468 TRACE("wait status changed after %lld, status 0x%02x\n",
469 elapsedTime
, status
);
474 if (elapsedTime
> timeout
) {
475 TRACE("wait timeout after %lld, status 0x%02x\n",
476 elapsedTime
, status
);
480 // The device may be ready almost immediatelly. If it isn't,
481 // poll often during the first 20ms, otherwise poll lazyly.
482 if (elapsedTime
< 1000)
484 else if (elapsedTime
< 20000)
495 ATAChannel::WaitDataRequest(bool high
)
497 return Wait(high
? ATA_STATUS_DATA_REQUEST
: 0,
498 high
? 0 : ATA_STATUS_DATA_REQUEST
, 0, (high
? 10 : 1) * 1000 * 1000);
503 ATAChannel::WaitDeviceReady()
505 return Wait(ATA_STATUS_DEVICE_READY
, 0, 0, 5 * 1000 * 1000);
510 ATAChannel::WaitForIdle()
512 return Wait(0, ATA_STATUS_BUSY
| ATA_STATUS_DATA_REQUEST
, 0, 50 * 1000);
517 ATAChannel::Interrupt(uint8 status
)
519 SpinLocker
locker(fInterruptLock
);
520 if (!fExpectsInterrupt
) {
521 TRACE("interrupt when not expecting transfer\n");
522 return B_UNHANDLED_INTERRUPT
;
525 if ((status
& ATA_STATUS_BUSY
) != 0) {
526 TRACE("interrupt while device is busy\n");
527 return B_UNHANDLED_INTERRUPT
;
530 TRACE("interrupt\n");
532 fInterruptCondition
.NotifyAll();
533 return B_INVOKE_SCHEDULER
;
538 ATAChannel::PrepareWaitingForInterrupt()
540 TRACE_FUNCTION("\n");
541 InterruptsSpinLocker
locker(fInterruptLock
);
542 fExpectsInterrupt
= true;
543 fInterruptCondition
.Add(&fInterruptConditionEntry
);
548 ATAChannel::WaitForInterrupt(bigtime_t timeout
)
550 TRACE_FUNCTION("timeout: %lld\n", timeout
);
551 status_t result
= fInterruptConditionEntry
.Wait(B_RELATIVE_TIMEOUT
,
554 InterruptsSpinLocker
locker(fInterruptLock
);
555 fExpectsInterrupt
= false;
558 if (result
!= B_OK
) {
559 TRACE_ERROR("timeout waiting for interrupt\n");
560 result
= RecoverLostInterrupt();
563 // disable interrupts
564 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
566 if (result
!= B_OK
) {
575 ATAChannel::RecoverLostInterrupt()
577 // read status to clear any pending interrupts
578 uint8 status
= _Status();
579 if (status
& (ATA_STATUS_BUSY
| ATA_STATUS_DATA_REQUEST
)) {
580 TRACE_ERROR("RecoverLostInterrupt: device busy, status 0x%02x\n", status
);
583 TRACE_ERROR("RecoverLostInterrupt: lost interrupt, status 0x%02x\n", status
);
589 ATAChannel::SendRequest(ATARequest
*request
, uint32 flags
)
591 // TODO: implement this:
592 // resetting the device here would discard current configuration,
593 // it's better when the SCSI bus manager requests an external reset.
595 TRACE_FUNCTION("\n");
596 ATADevice
*device
= request
->Device();
598 TRACE("SendRequest status 0x%02x\n", AltStatus());
600 if (request
->UseDMA())
601 _WriteControl(0); // enable interrupts
603 if (device
->Select() != B_OK
) {
604 TRACE_ERROR("device selection failed\n");
605 request
->SetStatus(SCSI_SEL_TIMEOUT
);
606 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
610 if (WaitForIdle() != B_OK
) {
611 TRACE_ERROR("device selection timeout\n");
612 request
->SetStatus(SCSI_SEL_TIMEOUT
);
613 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
617 if ((flags
& ATA_DEVICE_READY_REQUIRED
) != 0
618 && (AltStatus() & ATA_STATUS_DEVICE_READY
) == 0) {
619 TRACE_ERROR("device ready not set\n");
620 request
->SetStatus(SCSI_SEQUENCE_FAIL
);
621 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
625 if (_WriteRegs(device
->TaskFile(), device
->RegisterMask()
626 | ATA_MASK_COMMAND
) != B_OK
) {
627 TRACE_ERROR("can't write command\n");
628 request
->SetStatus(SCSI_HBA_ERR
);
629 _WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS
);
638 ATAChannel::FinishRequest(ATARequest
*request
, uint32 flags
, uint8 errorMask
)
640 TRACE_FUNCTION("\n");
641 if (flags
& ATA_WAIT_FINISH
) {
642 // wait for the device to finish current command (device no longer busy)
643 status_t result
= Wait(0, ATA_STATUS_BUSY
, flags
, request
->Timeout());
644 if (result
!= B_OK
) {
645 TRACE_ERROR("timeout waiting for request finish\n");
646 request
->SetStatus(SCSI_CMD_TIMEOUT
);
651 ata_task_file
*taskFile
= request
->Device()->TaskFile();
653 // read status, this also acknowledges pending interrupts
654 status_t result
= _ReadRegs(taskFile
, ATA_MASK_STATUS
| ATA_MASK_ERROR
);
655 if (result
!= B_OK
) {
656 TRACE("reading status failed\n");
657 request
->SetStatus(SCSI_SEQUENCE_FAIL
);
661 if (taskFile
->read
.status
& ATA_STATUS_BUSY
) {
662 TRACE("command failed, device still busy\n");
663 request
->SetStatus(SCSI_SEQUENCE_FAIL
);
667 if ((flags
& ATA_DEVICE_READY_REQUIRED
)
668 && (taskFile
->read
.status
& ATA_STATUS_DEVICE_READY
) == 0) {
669 TRACE("command failed, device ready required but not set\n");
670 request
->SetStatus(SCSI_SEQUENCE_FAIL
);
674 uint8 checkFlags
= ATA_STATUS_ERROR
;
675 if (flags
& ATA_CHECK_DEVICE_FAULT
)
676 checkFlags
|= ATA_STATUS_DEVICE_FAULT
;
678 if ((taskFile
->read
.status
& checkFlags
) == 0)
681 if ((taskFile
->read
.error
& ATA_ERROR_MEDIUM_CHANGED
)
682 != ATA_ERROR_MEDIUM_CHANGED
) {
683 TRACE_ERROR("command failed, error bit is set. status 0x%02x, error 0x%02x\n",
684 taskFile
->read
.status
, taskFile
->read
.error
);
687 uint8 error
= taskFile
->read
.error
& errorMask
;
688 if (error
& ATA_ERROR_INTERFACE_CRC
) {
689 TRACE_ERROR("interface crc error\n");
690 request
->SetSense(SCSIS_KEY_HARDWARE_ERROR
, SCSIS_ASC_LUN_COM_CRC
);
694 if (request
->IsWrite()) {
695 if (error
& ATA_ERROR_WRITE_PROTECTED
) {
696 request
->SetSense(SCSIS_KEY_DATA_PROTECT
, SCSIS_ASC_WRITE_PROTECTED
);
700 if (error
& ATA_ERROR_UNCORRECTABLE
) {
701 request
->SetSense(SCSIS_KEY_MEDIUM_ERROR
, SCSIS_ASC_UNREC_READ_ERR
);
706 if (error
& ATA_ERROR_MEDIUM_CHANGED
) {
707 request
->SetSense(SCSIS_KEY_UNIT_ATTENTION
, SCSIS_ASC_MEDIUM_CHANGED
);
711 if (error
& ATA_ERROR_INVALID_ADDRESS
) {
712 // XXX strange error code, don't really know what it means
713 request
->SetSense(SCSIS_KEY_MEDIUM_ERROR
, SCSIS_ASC_RANDOM_POS_ERROR
);
717 if (error
& ATA_ERROR_MEDIA_CHANGE_REQUESTED
) {
718 request
->SetSense(SCSIS_KEY_UNIT_ATTENTION
, SCSIS_ASC_REMOVAL_REQUESTED
);
722 if (error
& ATA_ERROR_NO_MEDIA
) {
723 request
->SetSense(SCSIS_KEY_MEDIUM_ERROR
, SCSIS_ASC_NO_MEDIUM
);
727 if (error
& ATA_ERROR_ABORTED
) {
728 request
->SetSense(SCSIS_KEY_ABORTED_COMMAND
, SCSIS_ASC_NO_SENSE
);
732 // either there was no error bit set or it was masked out
733 request
->SetSense(SCSIS_KEY_HARDWARE_ERROR
, SCSIS_ASC_INTERNAL_FAILURE
);
739 ATAChannel::PrepareDMA(ATARequest
*request
)
741 scsi_ccb
*ccb
= request
->CCB();
742 return fController
->prepare_dma(fCookie
, ccb
->sg_list
, ccb
->sg_count
,
748 ATAChannel::StartDMA()
750 return fController
->start_dma(fCookie
);
755 ATAChannel::FinishDMA()
757 return fController
->finish_dma(fCookie
);
762 ATAChannel::ExecutePIOTransfer(ATARequest
*request
)
764 bigtime_t timeout
= request
->Timeout();
765 status_t result
= B_OK
;
766 size_t *bytesLeft
= request
->BytesLeft();
767 while (*bytesLeft
> 0) {
768 size_t currentLength
= MIN(*bytesLeft
, request
->Device()->BlockSize());
769 if (request
->IsWrite()) {
770 result
= _WritePIOBlock(request
, currentLength
);
771 if (result
!= B_OK
) {
772 TRACE_ERROR("failed to write pio block\n");
776 result
= _ReadPIOBlock(request
, currentLength
);
777 if (result
!= B_OK
) {
778 TRACE_ERROR("failed to read pio block\n");
783 *bytesLeft
-= currentLength
;
785 if (*bytesLeft
> 0) {
786 // wait for next block to be ready
787 if (Wait(ATA_STATUS_DATA_REQUEST
, ATA_STATUS_BUSY
,
788 ATA_CHECK_ERROR_BIT
| ATA_CHECK_DEVICE_FAULT
,
790 TRACE_ERROR("timeout waiting for device to request data\n");
791 result
= B_TIMED_OUT
;
797 if (result
== B_OK
&& WaitDataRequest(false) != B_OK
) {
798 TRACE_ERROR("device still expects data transfer\n");
807 ATAChannel::ReadRegs(ATADevice
*device
)
809 return _ReadRegs(device
->TaskFile(), device
->RegisterMask());
814 ATAChannel::AltStatus()
816 return fController
->get_altstatus(fCookie
);
821 ATAChannel::ReadPIO(uint8
*buffer
, size_t length
)
823 return fController
->read_pio(fCookie
, (uint16
*)buffer
,
824 length
/ sizeof(uint16
), false);
829 ATAChannel::WritePIO(uint8
*buffer
, size_t length
)
831 return fController
->write_pio(fCookie
, (uint16
*)buffer
,
832 length
/ sizeof(uint16
), true);
837 ATAChannel::_ReadRegs(ata_task_file
*taskFile
, ata_reg_mask mask
)
839 return fController
->read_command_block_regs(fCookie
, taskFile
, mask
);
844 ATAChannel::_WriteRegs(ata_task_file
*taskFile
, ata_reg_mask mask
)
846 return fController
->write_command_block_regs(fCookie
, taskFile
, mask
);
851 ATAChannel::_Status()
853 ata_task_file taskFile
;
854 if (_ReadRegs(&taskFile
, ATA_MASK_STATUS
) != B_OK
)
856 return taskFile
.read
.status
;
861 ATAChannel::_WriteControl(uint8 value
)
863 return fController
->write_device_control(fCookie
, ATA_DEVICE_CONTROL_BIT3
869 ATAChannel::_FlushAndWait(bigtime_t waitTime
)
880 ATAChannel::_ReadPIOBlock(ATARequest
*request
, size_t length
)
882 uint32 transferred
= 0;
883 status_t result
= _TransferPIOBlock(request
, length
, &transferred
);
884 request
->CCB()->data_resid
-= transferred
;
886 // if length was odd, there's an extra byte waiting in request->OddByte()
887 if (request
->GetOddByte(NULL
)) {
888 // discard byte and adjust res_id as the extra byte didn't reach the
890 request
->CCB()->data_resid
++;
893 if (result
!= B_BUFFER_OVERFLOW
)
896 // the device returns more data then the buffer can store;
897 // for ATAPI this is OK - we just discard remaining bytes (there
898 // is no way to tell ATAPI about that, but we "only" waste time)
900 // perhaps discarding the extra odd-byte was sufficient
901 if (transferred
>= length
)
904 TRACE_ERROR("pio read: discarding after %lu bytes\n", transferred
);
907 length
-= transferred
;
908 // discard 32 bytes at once (see _WritePIOBlock())
910 // read extra byte if length is odd (that's the "length + 1")
911 size_t currentLength
= MIN(length
+ 1, (uint32
)sizeof(buffer
))
913 fController
->read_pio(fCookie
, (uint16
*)buffer
, currentLength
, false);
914 length
-= currentLength
* 2;
922 ATAChannel::_WritePIOBlock(ATARequest
*request
, size_t length
)
924 size_t transferred
= 0;
925 status_t result
= _TransferPIOBlock(request
, length
, &transferred
);
926 request
->CCB()->data_resid
-= transferred
;
928 if (result
!= B_BUFFER_OVERFLOW
)
931 // there may be a pending odd byte - transmit that now
933 if (request
->GetOddByte(&byte
)) {
938 fController
->write_pio(fCookie
, (uint16
*)buffer
, 1, false);
939 request
->CCB()->data_resid
--;
943 // "transferred" may actually be larger then length because the last odd-byte
944 // is sent together with an extra zero-byte
945 if (transferred
>= length
)
948 // Ouch! the device asks for data but we haven't got any left.
949 // Sadly, this behaviour is OK for ATAPI packets, but there is no
950 // way to tell the device that we don't have any data left;
951 // only solution is to send zero bytes, though it's BAD
952 static const uint8 buffer
[32] = {};
954 TRACE_ERROR("pio write: discarding after %lu bytes\n", transferred
);
956 length
-= transferred
;
958 // if device asks for odd number of bytes, append an extra byte to
959 // make length even (this is the "length + 1" term)
960 size_t currentLength
= MIN(length
+ 1, (int)(sizeof(buffer
)))
962 fController
->write_pio(fCookie
, (uint16
*)buffer
, currentLength
, false);
963 length
-= currentLength
* 2;
966 return B_BUFFER_OVERFLOW
;
971 ATAChannel::_TransferPIOBlock(ATARequest
*request
, size_t length
,
974 // data is usually split up into multiple scatter/gather blocks
976 if (request
->SGElementsLeft() == 0) {
977 // ups - buffer too small (for ATAPI data, this is OK)
978 return B_BUFFER_OVERFLOW
;
981 // we might have transmitted part of a scatter/entry already
982 const physical_entry
*entry
= request
->CurrentSGElement();
983 uint32 offset
= request
->CurrentSGOffset();
984 uint32 currentLength
= MIN(entry
->size
- offset
, length
);
986 status_t result
= _TransferPIOPhysical(request
,
987 entry
->address
+ offset
, currentLength
, transferred
);
988 if (result
!= B_OK
) {
989 request
->SetSense(SCSIS_KEY_HARDWARE_ERROR
,
990 SCSIS_ASC_INTERNAL_FAILURE
);
994 request
->AdvanceSG(currentLength
);
995 length
-= currentLength
;
1002 // TODO: this should not be necessary, we could directly use virtual addresses
1007 ATAChannel::_TransferPIOPhysical(ATARequest
*request
, addr_t physicalAddress
,
1008 size_t length
, size_t *transferred
)
1010 // we must split up chunk into B_PAGE_SIZE blocks as we can map only
1011 // one page into address space at once
1012 while (length
> 0) {
1013 Thread
*thread
= thread_get_current_thread();
1014 thread_pin_to_current_cpu(thread
);
1017 addr_t virtualAddress
;
1018 if (vm_get_physical_page_current_cpu(physicalAddress
, &virtualAddress
,
1020 thread_unpin_from_current_cpu(thread
);
1021 // ouch: this should never ever happen
1025 ASSERT(physicalAddress
% B_PAGE_SIZE
== virtualAddress
% B_PAGE_SIZE
);
1027 // if chunk starts in the middle of a page, we have even less then
1029 size_t pageLeft
= B_PAGE_SIZE
- physicalAddress
% B_PAGE_SIZE
;
1030 size_t currentLength
= MIN(pageLeft
, length
);
1032 status_t result
= _TransferPIOVirtual(request
, (uint8
*)virtualAddress
,
1033 currentLength
, transferred
);
1035 vm_put_physical_page_current_cpu(virtualAddress
, handle
);
1036 thread_unpin_from_current_cpu(thread
);
1041 length
-= currentLength
;
1042 physicalAddress
+= currentLength
;
1050 ATAChannel::_TransferPIOVirtual(ATARequest
*request
, uint8
*virtualAddress
,
1051 size_t length
, size_t *transferred
)
1053 if (request
->IsWrite()) {
1054 // if there is a byte left from last chunk, transmit it together
1055 // with the first byte of the current chunk (IDE requires 16 bits
1056 // to be transmitted at once)
1058 if (request
->GetOddByte(&byte
)) {
1062 buffer
[1] = *virtualAddress
++;
1064 fController
->write_pio(fCookie
, (uint16
*)buffer
, 1, false);
1070 fController
->write_pio(fCookie
, (uint16
*)virtualAddress
, length
/ 2,
1073 // take care if chunk size was odd, which means that 1 byte remains
1074 virtualAddress
+= length
& ~1;
1075 *transferred
+= length
& ~1;
1077 if ((length
& 1) != 0)
1078 request
->SetOddByte(*virtualAddress
);
1080 // if we read one byte too much last time, push it into current chunk
1082 if (request
->GetOddByte(&byte
)) {
1083 *virtualAddress
++ = byte
;
1087 fController
->read_pio(fCookie
, (uint16
*)virtualAddress
, length
/ 2,
1090 // take care of odd chunk size;
1091 // in this case we read 1 byte to few!
1092 virtualAddress
+= length
& ~1;
1093 *transferred
+= length
& ~1;
1095 if ((length
& 1) != 0) {
1098 // now read the missing byte; as we have to read 2 bytes at once,
1099 // we'll read one byte too much
1100 fController
->read_pio(fCookie
, (uint16
*)buffer
, 1, false);
1102 *virtualAddress
= buffer
[0];
1103 request
->SetOddByte(buffer
[1]);