Fix #8729.
[haiku.git] / src / add-ons / kernel / bus_managers / ata / ATAChannel.cpp
blob969ed2b3289366bfec635bce4e8f4a583eb5a16e
1 /*
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.
8 */
10 #include "ATAPrivate.h"
13 ATAChannel::ATAChannel(device_node *node)
15 fNode(node),
16 fChannelID(0),
17 fController(NULL),
18 fCookie(NULL),
19 fExpectsInterrupt(false),
20 fStatus(B_NO_INIT),
21 fSCSIBus(NULL),
22 fDeviceCount(0),
23 fDevices(NULL),
24 fUseDMA(true),
25 fRequest(NULL)
27 B_INITIALIZE_SPINLOCK(&fInterruptLock);
28 fInterruptCondition.Init(this, "ata dma transfer");
30 gDeviceManager->get_attr_uint32(node, ATA_CHANNEL_ID_ITEM, &fChannelID,
31 true);
32 snprintf(fDebugContext, sizeof(fDebugContext), " %lu", fChannelID);
34 if (fUseDMA) {
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");
40 fUseDMA = false;
43 unload_driver_settings(settings);
47 if (fUseDMA) {
48 uint8 canDMA;
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");
52 fUseDMA = false;
55 if (canDMA == 0) {
56 TRACE_ALWAYS("controller doesn't support DMA, disabling\n");
57 fUseDMA = false;
61 fRequest = new(std::nothrow) ATARequest(true);
62 if (fRequest == NULL) {
63 fStatus = B_NO_MEMORY;
64 return;
67 uint8 maxDevices = 2;
68 if (gDeviceManager->get_attr_uint8(node, ATA_CONTROLLER_MAX_DEVICES_ITEM,
69 &maxDevices, true) != B_OK) {
70 maxDevices = 2;
73 fDeviceCount = MIN(maxDevices, 2);
74 fDevices = new(std::nothrow) ATADevice *[fDeviceCount];
75 if (fDevices == NULL) {
76 fStatus = B_NO_MEMORY;
77 return;
80 for (uint8 i = 0; i < fDeviceCount; i++)
81 fDevices[i] = NULL;
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()
94 if (fDevices) {
95 for (uint8 i = 0; i < fDeviceCount; i++)
96 delete fDevices[i];
97 delete [] fDevices;
100 delete fRequest;
104 status_t
105 ATAChannel::InitCheck()
107 return fStatus;
111 void
112 ATAChannel::SetBus(scsi_bus bus)
114 fSCSIBus = bus;
118 bool
119 ATAChannel::_DevicePresent(int device)
121 SelectDevice(device);
123 if (SelectedDevice() != device) {
124 TRACE_ALWAYS("_DevicePresent: device selection failed for device %i\n",
125 device);
126 return false;
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");
135 return false;
137 if (_ReadRegs(&taskFile, ATA_MASK_SECTOR_COUNT
138 | ATA_MASK_SECTOR_NUMBER) != B_OK) {
139 TRACE_ERROR("_DevicePresent: reading registers failed\n");
140 return false;
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);
146 return present;
150 status_t
151 ATAChannel::ScanBus()
153 uint deviceMask = 0;
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");
161 return result;
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);
169 continue;
172 TRACE_ALWAYS("probing device %d\n", i);
173 SelectDevice(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",
183 status, i);
184 continue;
185 } else {
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);
193 continue;
196 // reselect device
197 SelectDevice(i);
198 WaitForIdle();
200 if (SelectedDevice() != i) {
201 TRACE_ALWAYS("device selection failed for device %i\n", i);
202 continue;
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");
209 return B_ERROR;
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);
228 else
229 device = new(std::nothrow) ATADevice(this, i);
231 if (device == NULL) {
232 TRACE_ERROR("out of memory allocating device\n");
233 return B_NO_MEMORY;
236 TRACE("trying ATA%s device %u\n", device->IsATAPI() ? "PI" : "", i);
238 if (device->Identify() != B_OK) {
239 delete device;
240 continue;
243 if (device->Configure() != B_OK) {
244 TRACE_ERROR("failed to configure device\n");
245 delete device;
246 continue;
249 TRACE_ALWAYS("identified ATA%s device %u\n", device->IsATAPI()
250 ? "PI" : "", i);
252 fDevices[i] = device;
255 return B_OK;
259 void
260 ATAChannel::PathInquiry(scsi_path_inquiry *info)
262 info->hba_inquiry = SCSI_PI_TAG_ABLE | SCSI_PI_WIDE_16;
263 info->hba_misc = 0;
264 info->sim_priv = 0;
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);
275 else
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);
285 void
286 ATAChannel::GetRestrictions(uint8 targetID, bool *isATAPI, bool *noAutoSense,
287 uint32 *maxBlocks)
289 // we always indicate ATAPI so we have to emulate fewer commands
290 *isATAPI = true;
291 *noAutoSense = false;
292 *maxBlocks = 0x100;
294 if (targetID < fDeviceCount && fDevices[targetID] != NULL)
295 fDevices[targetID]->GetRestrictions(noAutoSense, maxBlocks);
299 status_t
300 ATAChannel::ExecuteIO(scsi_ccb *ccb)
302 TRACE_FUNCTION("%p\n", ccb);
303 status_t result = fRequest->Start(ccb);
304 if (result != B_OK)
305 return result;
307 if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE && fRequest->HasSense()) {
308 TRACE("request sense\n");
309 fRequest->RequestSense();
310 fRequest->Finish(false);
311 return B_OK;
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);
321 return B_BAD_INDEX;
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);
329 return B_BAD_INDEX;
332 fRequest->SetTimeout(ccb->timeout > 0 ? ccb->timeout * 1000 * 1000
333 : ATA_STANDARD_TIMEOUT);
335 result = device->ExecuteIO(fRequest);
336 fRequest->Finish(false);
337 return result;
341 status_t
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);
347 return B_BAD_VALUE;
351 status_t
352 ATAChannel::SelectDevice(uint8 device)
354 TRACE_FUNCTION("device: %u\n", device);
356 if (device > 1)
357 return B_BAD_INDEX;
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",
367 device);
368 return result;
371 _FlushAndWait(1);
373 return B_OK;
377 uint8
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.
387 return 234;
390 return taskFile.lba.device;
394 status_t
395 ATAChannel::Reset()
397 TRACE_FUNCTION("\n");
399 SelectDevice(0);
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");
405 return B_ERROR;
408 _FlushAndWait(20);
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");
413 return B_ERROR;
416 _FlushAndWait(150 * 1000);
418 // read status to clear any pending interrupts
419 _Status();
421 return B_OK;
425 status_t
426 ATAChannel::Wait(uint8 setBits, uint8 clearedBits, uint32 flags,
427 bigtime_t timeout)
429 bigtime_t startTime = system_time();
430 _FlushAndWait(1);
432 TRACE("wait for set bits 0x%02x and cleared bits 0x%02x\n",
433 setBits, clearedBits);
435 #if ATA_TRACING
436 unsigned lastStatus = 0x100;
437 #endif
438 while (true) {
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);
444 return B_ERROR;
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);
451 return B_ERROR;
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);
457 return B_OK;
459 if ((status & setBits) == setBits) {
460 TRACE("wait success, status 0x%02x\n", status);
461 return B_OK;
465 bigtime_t elapsedTime = system_time() - startTime;
466 #if ATA_TRACING
467 if (lastStatus != status) {
468 TRACE("wait status changed after %lld, status 0x%02x\n",
469 elapsedTime, status);
470 lastStatus = status;
472 #endif
474 if (elapsedTime > timeout) {
475 TRACE("wait timeout after %lld, status 0x%02x\n",
476 elapsedTime, status);
477 return B_TIMED_OUT;
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)
483 spin(1);
484 else if (elapsedTime < 20000)
485 snooze(1000);
486 else
487 snooze(50000);
490 return B_ERROR;
494 status_t
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);
502 status_t
503 ATAChannel::WaitDeviceReady()
505 return Wait(ATA_STATUS_DEVICE_READY, 0, 0, 5 * 1000 * 1000);
509 status_t
510 ATAChannel::WaitForIdle()
512 return Wait(0, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, 0, 50 * 1000);
516 status_t
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;
537 void
538 ATAChannel::PrepareWaitingForInterrupt()
540 TRACE_FUNCTION("\n");
541 InterruptsSpinLocker locker(fInterruptLock);
542 fExpectsInterrupt = true;
543 fInterruptCondition.Add(&fInterruptConditionEntry);
547 status_t
548 ATAChannel::WaitForInterrupt(bigtime_t timeout)
550 TRACE_FUNCTION("timeout: %lld\n", timeout);
551 status_t result = fInterruptConditionEntry.Wait(B_RELATIVE_TIMEOUT,
552 timeout);
554 InterruptsSpinLocker locker(fInterruptLock);
555 fExpectsInterrupt = false;
556 locker.Unlock();
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) {
567 return B_TIMED_OUT;
570 return B_OK;
574 status_t
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);
581 return B_ERROR;
583 TRACE_ERROR("RecoverLostInterrupt: lost interrupt, status 0x%02x\n", status);
584 return B_OK;
588 status_t
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);
607 return B_TIMED_OUT;
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);
614 return B_TIMED_OUT;
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);
622 return B_ERROR;
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);
630 return B_ERROR;
633 return B_OK;
637 status_t
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);
647 return result;
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);
658 return result;
661 if (taskFile->read.status & ATA_STATUS_BUSY) {
662 TRACE("command failed, device still busy\n");
663 request->SetStatus(SCSI_SEQUENCE_FAIL);
664 return B_ERROR;
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);
671 return B_ERROR;
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)
679 return B_OK;
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);
691 return B_ERROR;
694 if (request->IsWrite()) {
695 if (error & ATA_ERROR_WRITE_PROTECTED) {
696 request->SetSense(SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED);
697 return B_ERROR;
699 } else {
700 if (error & ATA_ERROR_UNCORRECTABLE) {
701 request->SetSense(SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR);
702 return B_ERROR;
706 if (error & ATA_ERROR_MEDIUM_CHANGED) {
707 request->SetSense(SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED);
708 return B_ERROR;
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);
714 return B_ERROR;
717 if (error & ATA_ERROR_MEDIA_CHANGE_REQUESTED) {
718 request->SetSense(SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED);
719 return B_ERROR;
722 if (error & ATA_ERROR_NO_MEDIA) {
723 request->SetSense(SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_NO_MEDIUM);
724 return B_ERROR;
727 if (error & ATA_ERROR_ABORTED) {
728 request->SetSense(SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE);
729 return B_ERROR;
732 // either there was no error bit set or it was masked out
733 request->SetSense(SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE);
734 return B_ERROR;
738 status_t
739 ATAChannel::PrepareDMA(ATARequest *request)
741 scsi_ccb *ccb = request->CCB();
742 return fController->prepare_dma(fCookie, ccb->sg_list, ccb->sg_count,
743 request->IsWrite());
747 status_t
748 ATAChannel::StartDMA()
750 return fController->start_dma(fCookie);
754 status_t
755 ATAChannel::FinishDMA()
757 return fController->finish_dma(fCookie);
761 status_t
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");
773 break;
775 } else {
776 result = _ReadPIOBlock(request, currentLength);
777 if (result != B_OK) {
778 TRACE_ERROR("failed to read pio block\n");
779 break;
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,
789 timeout) != B_OK) {
790 TRACE_ERROR("timeout waiting for device to request data\n");
791 result = B_TIMED_OUT;
792 break;
797 if (result == B_OK && WaitDataRequest(false) != B_OK) {
798 TRACE_ERROR("device still expects data transfer\n");
799 result = B_ERROR;
802 return result;
806 status_t
807 ATAChannel::ReadRegs(ATADevice *device)
809 return _ReadRegs(device->TaskFile(), device->RegisterMask());
813 uint8
814 ATAChannel::AltStatus()
816 return fController->get_altstatus(fCookie);
820 status_t
821 ATAChannel::ReadPIO(uint8 *buffer, size_t length)
823 return fController->read_pio(fCookie, (uint16 *)buffer,
824 length / sizeof(uint16), false);
828 status_t
829 ATAChannel::WritePIO(uint8 *buffer, size_t length)
831 return fController->write_pio(fCookie, (uint16 *)buffer,
832 length / sizeof(uint16), true);
836 status_t
837 ATAChannel::_ReadRegs(ata_task_file *taskFile, ata_reg_mask mask)
839 return fController->read_command_block_regs(fCookie, taskFile, mask);
843 status_t
844 ATAChannel::_WriteRegs(ata_task_file *taskFile, ata_reg_mask mask)
846 return fController->write_command_block_regs(fCookie, taskFile, mask);
850 uint8
851 ATAChannel::_Status()
853 ata_task_file taskFile;
854 if (_ReadRegs(&taskFile, ATA_MASK_STATUS) != B_OK)
855 return 0x01;
856 return taskFile.read.status;
860 status_t
861 ATAChannel::_WriteControl(uint8 value)
863 return fController->write_device_control(fCookie, ATA_DEVICE_CONTROL_BIT3
864 | value);
868 void
869 ATAChannel::_FlushAndWait(bigtime_t waitTime)
871 AltStatus();
872 if (waitTime > 100)
873 snooze(waitTime);
874 else
875 spin(waitTime);
879 status_t
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
889 // buffer
890 request->CCB()->data_resid++;
893 if (result != B_BUFFER_OVERFLOW)
894 return result;
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)
902 return B_OK;
904 TRACE_ERROR("pio read: discarding after %lu bytes\n", transferred);
906 uint8 buffer[32];
907 length -= transferred;
908 // discard 32 bytes at once (see _WritePIOBlock())
909 while (length > 0) {
910 // read extra byte if length is odd (that's the "length + 1")
911 size_t currentLength = MIN(length + 1, (uint32)sizeof(buffer))
912 / sizeof(uint16);
913 fController->read_pio(fCookie, (uint16 *)buffer, currentLength, false);
914 length -= currentLength * 2;
917 return B_OK;
921 status_t
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)
929 return result;
931 // there may be a pending odd byte - transmit that now
932 uint8 byte;
933 if (request->GetOddByte(&byte)) {
934 uint8 buffer[2];
935 buffer[0] = byte;
936 buffer[1] = 0;
938 fController->write_pio(fCookie, (uint16 *)buffer, 1, false);
939 request->CCB()->data_resid--;
940 transferred += 2;
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)
946 return B_OK;
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;
957 while (length > 0) {
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)))
961 / sizeof(uint16);
962 fController->write_pio(fCookie, (uint16 *)buffer, currentLength, false);
963 length -= currentLength * 2;
966 return B_BUFFER_OVERFLOW;
970 status_t
971 ATAChannel::_TransferPIOBlock(ATARequest *request, size_t length,
972 size_t *transferred)
974 // data is usually split up into multiple scatter/gather blocks
975 while (length > 0) {
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);
991 return result;
994 request->AdvanceSG(currentLength);
995 length -= currentLength;
998 return B_OK;
1002 // TODO: this should not be necessary, we could directly use virtual addresses
1003 #include <vm/vm.h>
1004 #include <thread.h>
1006 status_t
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);
1016 void *handle;
1017 addr_t virtualAddress;
1018 if (vm_get_physical_page_current_cpu(physicalAddress, &virtualAddress,
1019 &handle) != B_OK) {
1020 thread_unpin_from_current_cpu(thread);
1021 // ouch: this should never ever happen
1022 return B_ERROR;
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
1028 // a page left
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);
1038 if (result != B_OK)
1039 return result;
1041 length -= currentLength;
1042 physicalAddress += currentLength;
1045 return B_OK;
1049 status_t
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)
1057 uint8 byte;
1058 if (request->GetOddByte(&byte)) {
1059 uint8 buffer[2];
1061 buffer[0] = byte;
1062 buffer[1] = *virtualAddress++;
1064 fController->write_pio(fCookie, (uint16 *)buffer, 1, false);
1066 length--;
1067 *transferred += 2;
1070 fController->write_pio(fCookie, (uint16 *)virtualAddress, length / 2,
1071 false);
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);
1079 } else {
1080 // if we read one byte too much last time, push it into current chunk
1081 uint8 byte;
1082 if (request->GetOddByte(&byte)) {
1083 *virtualAddress++ = byte;
1084 length--;
1087 fController->read_pio(fCookie, (uint16 *)virtualAddress, length / 2,
1088 false);
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) {
1096 uint8 buffer[2];
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]);
1105 *transferred += 2;
1109 return B_OK;