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.
6 *
7 * Distributed under the terms of the MIT License.
8 */
9
10#include "ATAPrivate.h"
11
12
13ATADevice::ATADevice(ATAChannel *channel, uint8 index)
14	:
15	fChannel(channel),
16	fRegisterMask(0),
17	fUseDMA(channel->UseDMA()),
18	fDMAMode(0),
19	fDMAFailures(0),
20	fTotalSectors(0),
21	fBlockSize(512),
22	fPhysicalBlockSize(512),
23	fBlockOffset(0),
24	fIndex(index),
25	fUse48Bits(false)
26{
27	memset(&fInfoBlock, 0, sizeof(fInfoBlock));
28	memset(&fTaskFile, 0, sizeof(fTaskFile));
29}
30
31
32ATADevice::~ATADevice()
33{
34}
35
36
37status_t
38ATADevice::TestUnitReady(ATARequest *request)
39{
40	TRACE_FUNCTION("%p\n", request);
41
42	fRegisterMask = 0;
43	fTaskFile.write.command = ATA_COMMAND_GET_MEDIA_STATUS;
44
45	request->SetTimeout(15 * 1000 * 1000);
46	status_t result = fChannel->SendRequest(request, ATA_DEVICE_READY_REQUIRED);
47	if (result != B_OK) {
48		TRACE_ERROR("failed to send test unit ready request\n");
49		return result;
50	}
51
52	return fChannel->FinishRequest(request, ATA_WAIT_FINISH
53		| ATA_DEVICE_READY_REQUIRED, ATA_ERROR_NO_MEDIA | ATA_ERROR_ABORTED
54		| ATA_ERROR_MEDIA_CHANGE_REQUESTED | ATA_ERROR_MEDIUM_CHANGED);
55}
56
57
58status_t
59ATADevice::SynchronizeCache(ATARequest *request)
60{
61	TRACE_FUNCTION("%p\n", request);
62
63	// we should also ask for FLUSH CACHE support, but everyone denies it
64	// (looks like they cheat to gain some performance advantage, but
65	//  that's pretty useless: everyone does it...)
66	if (!fInfoBlock.write_cache_supported)
67		return B_OK;
68
69	fRegisterMask = 0;
70	fTaskFile.lba.command
71		= fUse48Bits ? ATA_COMMAND_FLUSH_CACHE_EXT : ATA_COMMAND_FLUSH_CACHE;
72
73	request->SetTimeout(60 * 1000 * 1000);
74	status_t result = fChannel->SendRequest(request, ATA_DEVICE_READY_REQUIRED);
75	if (result != B_OK) {
76		TRACE_ERROR("failed to send synchronize cache request\n");
77		return result;
78	}
79
80	return fChannel->FinishRequest(request, ATA_WAIT_FINISH
81		| ATA_DEVICE_READY_REQUIRED, ATA_ERROR_ABORTED);
82}
83
84
85status_t
86ATADevice::Eject(ATARequest *request)
87{
88	TRACE_FUNCTION("%p\n", request);
89
90	fRegisterMask = 0;
91	fTaskFile.lba.command = ATA_COMMAND_MEDIA_EJECT;
92
93	request->SetTimeout(15 * 1000 * 1000);
94	status_t result = fChannel->SendRequest(request, ATA_DEVICE_READY_REQUIRED);
95	if (result != B_OK) {
96		TRACE_ERROR("failed to send eject request\n");
97		return result;
98	}
99
100	return fChannel->FinishRequest(request, ATA_WAIT_FINISH
101		| ATA_DEVICE_READY_REQUIRED, ATA_ERROR_ABORTED | ATA_ERROR_NO_MEDIA);
102}
103
104
105status_t
106ATADevice::Inquiry(ATARequest *request)
107{
108	TRACE_FUNCTION("%p\n", request);
109
110	scsi_ccb *ccb = request->CCB();
111	scsi_cmd_inquiry *command = (scsi_cmd_inquiry *)ccb->cdb;
112	if (command->evpd || command->page_code) {
113		request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
114		return B_ERROR;
115	}
116
117	scsi_res_inquiry data;
118	memset(&data, 0, sizeof(data));
119
120	data.device_type = IsATAPI()
121		? fInfoBlock.word_0.atapi.command_packet_set : scsi_dev_direct_access;
122	data.device_qualifier = scsi_periph_qual_connected;
123
124	data.device_type_modifier = 0;
125	data.removable_medium = fInfoBlock.word_0.ata.removable_media_device;
126
127	data.ansi_version = 2;
128	data.ecma_version = 0;
129	data.iso_version = 0;
130
131	data.response_data_format = 2;
132	data.term_iop = false;
133		// to be changed if we support TERM I/O
134
135	data.additional_length = sizeof(scsi_res_inquiry) - 4;
136
137	data.soft_reset = false;
138	data.cmd_queue = 0;
139	data.linked = false;
140
141	// these values are free-style
142	data.sync = false;
143	data.write_bus16 = true;
144	data.write_bus32 = false;
145
146	data.relative_address = false;
147
148	// the following fields are *much* to small, sigh...
149	memcpy(data.vendor_ident, fInfoBlock.model_number,
150		sizeof(data.vendor_ident));
151	swap_words(data.vendor_ident, sizeof(data.vendor_ident));
152
153	memcpy(data.product_ident, fInfoBlock.model_number + 8,
154		sizeof(data.product_ident));
155	swap_words(data.product_ident, sizeof(data.product_ident));
156
157	memcpy(data.product_rev, "    ", sizeof(data.product_rev));
158
159	uint32 allocationLength = command->allocation_length;
160	copy_sg_data(ccb, 0, allocationLength, &data, sizeof(data), false);
161	ccb->data_resid = ccb->data_length - MIN(MIN(sizeof(data),
162		allocationLength), ccb->data_length);
163	return B_OK;
164}
165
166
167status_t
168ATADevice::ReadCapacity(ATARequest *request)
169{
170	TRACE_FUNCTION("%p\n", request);
171
172	scsi_ccb *ccb = request->CCB();
173	scsi_cmd_read_capacity *command = (scsi_cmd_read_capacity *)ccb->cdb;
174	if (command->pmi || command->lba) {
175		request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
176		return B_ERROR;
177	}
178
179	scsi_res_read_capacity data;
180	data.block_size = B_HOST_TO_BENDIAN_INT32(fBlockSize);
181
182	if (fTotalSectors <= UINT_MAX) {
183		uint32 lastBlock = fTotalSectors - 1;
184		data.lba = B_HOST_TO_BENDIAN_INT32(lastBlock);
185	} else
186		data.lba = UINT_MAX;
187	TRACE("returning last block: %lu\n", B_BENDIAN_TO_HOST_INT32(data.lba));
188
189	copy_sg_data(ccb, 0, ccb->data_length, &data, sizeof(data), false);
190	ccb->data_resid = MAX(ccb->data_length - sizeof(data), 0);
191	return B_OK;
192}
193
194
195status_t
196ATADevice::ReadCapacity16(ATARequest *request)
197{
198	TRACE_FUNCTION("%p\n", request);
199
200	scsi_ccb *ccb = request->CCB();
201	scsi_res_read_capacity_long data;
202	data.block_size = B_HOST_TO_BENDIAN_INT32(fBlockSize);
203
204	uint64 lastBlock = fTotalSectors - 1;
205	data.lba = B_HOST_TO_BENDIAN_INT64(lastBlock);
206	TRACE("returning last block: %llu\n", data.lba);
207
208	copy_sg_data(ccb, 0, ccb->data_length, &data, sizeof(data), false);
209	ccb->data_resid = MAX(ccb->data_length - sizeof(data), 0);
210	return B_OK;
211}
212
213
214status_t
215ATADevice::ExecuteIO(ATARequest *request)
216{
217	TRACE_FUNCTION("%p\n", request);
218
219	scsi_ccb *ccb = request->CCB();
220	request->SetDevice(this);
221
222	// ATA devices have one LUN only
223	if (ccb->target_lun != 0) {
224		TRACE_ERROR("invalid target lun %d for ATA device\n", ccb->target_lun);
225		request->SetStatus(SCSI_SEL_TIMEOUT);
226		return B_BAD_INDEX;
227	}
228
229	TRACE("request: 0x%02x\n", ccb->cdb[0]);
230
231	switch (ccb->cdb[0]) {
232		case SCSI_OP_TEST_UNIT_READY:
233			return TestUnitReady(request);
234
235		case SCSI_OP_FORMAT: /* FORMAT UNIT */
236			// we could forward ccb to disk, but modern disks cannot
237			// be formatted anyway, so we just refuse ccb
238			// (exceptions are removable media devices, but to my knowledge
239			// they don't have to be formatted as well)
240			request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
241			return B_ERROR;
242
243		case SCSI_OP_INQUIRY:
244 			return Inquiry(request);
245
246		case SCSI_OP_START_STOP:
247		{
248			scsi_cmd_ssu *command = (scsi_cmd_ssu *)ccb->cdb;
249
250			// with no LoEj bit set, we should only allow/deny further access
251			// we ignore that (unsupported for ATA)
252			// with LoEj bit set, we should additionally either load or eject
253			// the medium (start = 0 - eject; start = 1 - load)
254
255			if (!command->start) {
256				// we must always flush cache if start = 0
257				SynchronizeCache(request);
258			}
259
260			if (command->load_eject) {
261				if (!command->start)
262					return Eject(request);
263				else {
264					request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST,
265						SCSIS_ASC_PARAM_NOT_SUPPORTED);
266					return B_ERROR;
267				}
268			}
269
270			return B_OK;
271		}
272
273		case SCSI_OP_READ_CAPACITY:
274			return ReadCapacity(request);
275
276		case SCSI_OP_SERVICE_ACTION_IN:
277			if ((ccb->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16)
278				return ReadCapacity16(request);
279			break;
280
281		case SCSI_OP_SYNCHRONIZE_CACHE:
282			// we ignore range and immediate bit, we always immediately
283			// flush everything
284			return SynchronizeCache(request);
285
286		// sadly, there are two possible read/write operation codes;
287		// at least, the third one, read/write(12), is not valid for DAS
288		case SCSI_OP_READ_6:
289		case SCSI_OP_WRITE_6:
290		{
291			scsi_cmd_rw_6 *command = (scsi_cmd_rw_6 *)ccb->cdb;
292			uint32 address = ((uint32)command->high_lba << 16)
293				| ((uint32)command->mid_lba << 8) | (uint32)command->low_lba;
294
295			request->SetIsWrite(command->opcode == SCSI_OP_WRITE_6);
296			return ExecuteReadWrite(request, address, command->length != 0
297				? command->length : 256);
298		}
299
300		case SCSI_OP_READ_10:
301		case SCSI_OP_WRITE_10:
302		{
303			scsi_cmd_rw_10 *command = (scsi_cmd_rw_10 *)ccb->cdb;
304			uint32 address = B_BENDIAN_TO_HOST_INT32(command->lba);
305			uint32 sectorCount = B_BENDIAN_TO_HOST_INT16(command->length);
306
307			request->SetIsWrite(command->opcode == SCSI_OP_WRITE_10);
308			if (sectorCount > 0)
309				return ExecuteReadWrite(request, address, sectorCount);
310			else {
311				// we cannot transfer zero blocks (apart from LBA48)
312				request->SetStatus(SCSI_REQ_CMP);
313				return B_OK;
314			}
315		}
316
317		case SCSI_OP_READ_12:
318		case SCSI_OP_WRITE_12:
319		{
320			scsi_cmd_rw_12 *command = (scsi_cmd_rw_12 *)ccb->cdb;
321			uint32 address = B_BENDIAN_TO_HOST_INT32(command->lba);
322			uint32 sectorCount = B_BENDIAN_TO_HOST_INT32(command->length);
323
324			request->SetIsWrite(command->opcode == SCSI_OP_WRITE_12);
325			if (sectorCount > 0)
326				return ExecuteReadWrite(request, address, sectorCount);
327			else {
328				// we cannot transfer zero blocks (apart from LBA48)
329				request->SetStatus(SCSI_REQ_CMP);
330				return B_OK;
331			}
332		}
333
334		case SCSI_OP_READ_16:
335		case SCSI_OP_WRITE_16:
336		{
337			scsi_cmd_rw_16 *command = (scsi_cmd_rw_16 *)ccb->cdb;
338			uint64 address = B_BENDIAN_TO_HOST_INT64(command->lba);
339			uint32 sectorCount = B_BENDIAN_TO_HOST_INT32(command->length);
340
341			request->SetIsWrite(command->opcode == SCSI_OP_WRITE_16);
342			if (sectorCount > 0)
343				return ExecuteReadWrite(request, address, sectorCount);
344			else {
345				// we cannot transfer zero blocks (apart from LBA48)
346				request->SetStatus(SCSI_REQ_CMP);
347				return B_OK;
348			}
349		}
350	}
351
352	TRACE("command not implemented\n");
353	request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
354	return B_ERROR;
355}
356
357
358void
359ATADevice::GetRestrictions(bool *noAutoSense, uint32 *maxBlocks)
360{
361	if (IsATAPI())
362		*noAutoSense = true;
363	else {
364		if (fUse48Bits)
365			*maxBlocks = 0xffff;
366		else
367			*maxBlocks = 0x100;
368	}
369}
370
371
372status_t
373ATADevice::Control(uint32 opcode, void *buffer, size_t length)
374{
375	if (opcode == B_GET_DEVICE_NAME) {
376		// Swap words
377		char name[sizeof(fInfoBlock.model_number)];
378		memcpy(name, fInfoBlock.model_number, sizeof(name));
379		swap_words(name, sizeof(name));
380
381		// Remove trailing spaces
382		int32 nameLength = sizeof(name) - 2;
383		while (nameLength > 0 && name[nameLength - 1] == ' ')
384			nameLength--;
385
386		// TODO: make string prettier, ie. "WDC" -> "Western Digital", ...
387		return user_strlcpy((char*)buffer, name,
388			min_c((size_t)nameLength + 1, length)) >= 0 ? B_OK : B_BAD_ADDRESS;
389	}
390	return B_BAD_VALUE;
391}
392
393
394status_t
395ATADevice::Select()
396{
397	status_t err = fChannel->SelectDevice(fIndex);
398#if 1
399    // for debugging only
400	if (fChannel->SelectedDevice() != fIndex) {
401		TRACE_ERROR("device %d not selected!\n", fIndex);
402		return B_ERROR;
403	}
404#endif
405	return err;
406}
407
408
409status_t
410ATADevice::SetFeature(int feature)
411{
412	TRACE("device_set_feature: feature %d\n", feature);
413
414	ATARequest request(false);
415	request.SetDevice(this);
416	request.SetTimeout(1 * 1000 * 1000);
417
418	fTaskFile.write.features = feature;
419	fTaskFile.write.command = ATA_COMMAND_SET_FEATURES;
420	fRegisterMask = ATA_MASK_FEATURES;
421
422	status_t result = fChannel->SendRequest(&request, ATA_DEVICE_READY_REQUIRED);
423	if (result != B_OK) {
424		TRACE_ERROR("sending set feature request failed\n");
425		return result;
426	}
427
428	result = fChannel->FinishRequest(&request,
429		ATA_WAIT_FINISH | ATA_DEVICE_READY_REQUIRED, ATA_ERROR_ABORTED);
430	if (result != B_OK) {
431		TRACE_ERROR("set feature request failed\n");
432		return result;
433	}
434
435	return B_OK;
436}
437
438
439status_t
440ATADevice::DisableCommandQueueing()
441{
442	if (!fInfoBlock.read_write_dma_queued_supported)
443		return B_OK;
444
445	if (fInfoBlock.release_interrupt_supported) {
446		status_t result = SetFeature(
447			ATA_COMMAND_SET_FEATURES_DISABLE_RELEASE_INT);
448		if (result != B_OK) {
449			TRACE_ERROR("failed to disable release interrupt\n");
450			return result;
451		}
452	}
453
454	if (fInfoBlock.service_interrupt_supported) {
455		status_t result = SetFeature(
456			ATA_COMMAND_SET_FEATURES_DISABLE_SERVICE_INT);
457		if (result != B_OK) {
458			TRACE_ERROR("failed to disable service interrupt\n");
459			return result;
460		}
461	}
462
463	return B_OK;
464}
465
466
467status_t
468ATADevice::ConfigureDMA()
469{
470	if (!fUseDMA)
471		return B_OK;
472
473	if (!fInfoBlock.dma_supported) {
474		TRACE_ALWAYS("DMA not supported by device\n");
475		fUseDMA = false;
476		return B_OK;
477	}
478
479	#define CHECK_DMA_MODE(element, mode) \
480		if (fInfoBlock.element) { \
481			fDMAMode = mode; \
482			modeCount++; \
483		}
484
485	uint32 modeCount = 0;
486
487	CHECK_DMA_MODE(multiword_dma_0_selected, 0x00);
488	CHECK_DMA_MODE(multiword_dma_1_selected, 0x01);
489	CHECK_DMA_MODE(multiword_dma_2_selected, 0x02);
490
491	if (fInfoBlock.word_88_valid) {
492		CHECK_DMA_MODE(ultra_dma_0_selected, 0x10);
493		CHECK_DMA_MODE(ultra_dma_1_selected, 0x11);
494		CHECK_DMA_MODE(ultra_dma_2_selected, 0x12);
495		CHECK_DMA_MODE(ultra_dma_3_selected, 0x13);
496		CHECK_DMA_MODE(ultra_dma_4_selected, 0x14);
497		CHECK_DMA_MODE(ultra_dma_5_selected, 0x15);
498		CHECK_DMA_MODE(ultra_dma_6_selected, 0x16);
499	}
500
501	#undef CHECK_DMA_MODE
502
503	if (modeCount != 1) {
504		TRACE_ERROR("more than one DMA mode selected, not using DMA\n");
505		fUseDMA = false;
506		return B_OK;
507	}
508
509	TRACE_ALWAYS("using DMA mode 0x%02x\n", fDMAMode);
510	return B_OK;
511}
512
513
514status_t
515ATADevice::Configure()
516{
517	// warning: ata == 0 means "this is ata"...
518	if (fInfoBlock.word_0.ata.ata_device != ATA_WORD_0_ATA_DEVICE) {
519		// CF has either magic header or CFA bit set
520		// we merge it to "CFA bit set" for easier (later) testing
521		if (fInfoBlock.word_0.raw == ATA_WORD_0_CFA_MAGIC)
522			fInfoBlock.compact_flash_assoc_supported = true;
523		else {
524			TRACE_ERROR("infoblock indicates non-ata device\n");
525			return B_ERROR;
526		}
527	}
528
529	if (!fInfoBlock.lba_supported || (fInfoBlock.lba_sector_count == 0
530		&& fInfoBlock.lba48_sector_count == 0)) {
531		TRACE_ERROR("non-lba devices not supported\n");
532		return B_ERROR;
533	}
534
535	fTotalSectors = fInfoBlock.SectorCount(fUse48Bits, false);
536	fBlockSize = fInfoBlock.SectorSize();
537	fPhysicalBlockSize = fInfoBlock.PhysicalSectorSize();
538	fBlockOffset = fInfoBlock.BlockOffset();
539
540	fTaskFile.lba.mode = ATA_MODE_LBA;
541	fTaskFile.lba.device = fIndex;
542
543	status_t result = ConfigureDMA();
544	if (result != B_OK)
545		return result;
546
547	result = DisableCommandQueueing();
548	if (result != B_OK)
549		return result;
550
551	return B_OK;
552}
553
554
555status_t
556ATADevice::Identify()
557{
558	snprintf(fDebugContext, sizeof(fDebugContext), "%s %" B_PRIu32 "-%u",
559		IsATAPI() ? "pi" : "", fChannel->ChannelID(), fIndex);
560
561	ATARequest request(false);
562	request.SetDevice(this);
563	request.SetTimeout(20 * 1000 * 1000);
564
565	fRegisterMask = 0;
566	fTaskFile.write.command = IsATAPI() ? ATA_COMMAND_IDENTIFY_PACKET_DEVICE
567		: ATA_COMMAND_IDENTIFY_DEVICE;
568
569	if (fChannel->SendRequest(&request,
570			IsATAPI() ? 0 : ATA_DEVICE_READY_REQUIRED) != B_OK) {
571		TRACE_ERROR("sending identify request failed\n");
572		return B_ERROR;
573	}
574
575	if (fChannel->Wait(ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, 0,
576			ATA_WAIT_ANY_BIT, 100 * 1000) != B_OK) {
577		TRACE_ALWAYS("no data request and not busy within 100ms, assuming "
578			"no device present\n");
579		return B_TIMED_OUT;
580	}
581
582	if (fChannel->Wait(ATA_STATUS_DATA_REQUEST, ATA_STATUS_BUSY,
583			ATA_CHECK_ERROR_BIT | ATA_CHECK_DEVICE_FAULT,
584			IsATAPI() ? 20 * 1000 * 1000 : 500 * 1000) != B_OK) {
585		TRACE_ERROR("timeout waiting for identify request\n");
586		return B_TIMED_OUT;
587	}
588
589	// get the infoblock
590	fChannel->ReadPIO((uint8 *)&fInfoBlock, sizeof(fInfoBlock));
591
592	if (fChannel->WaitDataRequest(false) != B_OK) {
593		TRACE_ERROR("device disagrees on info block length\n");
594		return B_ERROR;
595	}
596
597	if (fChannel->FinishRequest(&request,
598			ATA_WAIT_FINISH | (IsATAPI() ? 0 : ATA_DEVICE_READY_REQUIRED),
599			ATA_ERROR_ABORTED) != B_OK) {
600		TRACE_ERROR("failed to finish identify request\n");
601		return B_ERROR;
602	}
603
604	if (1) {
605		// print device information
606		char modelNumber[sizeof(fInfoBlock.model_number) + 1];
607		char serialNumber[sizeof(fInfoBlock.serial_number) + 1];
608		char firmwareRev[sizeof(fInfoBlock.firmware_revision) + 1];
609		strlcpy(modelNumber, fInfoBlock.model_number, sizeof(modelNumber));
610		strlcpy(serialNumber, fInfoBlock.serial_number, sizeof(serialNumber));
611		strlcpy(firmwareRev, fInfoBlock.firmware_revision, sizeof(firmwareRev));
612		swap_words(modelNumber, sizeof(modelNumber) - 1);
613		swap_words(serialNumber, sizeof(serialNumber) - 1);
614		swap_words(firmwareRev, sizeof(firmwareRev) - 1);
615		TRACE_ALWAYS("model number: %s\n", modelNumber);
616		TRACE_ALWAYS("serial number: %s\n", serialNumber);
617  		TRACE_ALWAYS("firmware rev.: %s\n", firmwareRev);
618	}
619
620	return B_OK;
621}
622
623
624status_t
625ATADevice::ExecuteReadWrite(ATARequest *request, uint64 address,
626	uint32 sectorCount)
627{
628	request->SetUseDMA(fUseDMA && fChannel->PrepareDMA(request) == B_OK);
629	if (!request->UseDMA())
630		request->PrepareSGInfo();
631
632	request->SetBytesLeft(sectorCount * fBlockSize);
633	if (_FillTaskFile(request, address) != B_OK) {
634		TRACE_ERROR("failed to setup transfer request\n");
635		if (request->UseDMA())
636			fChannel->FinishDMA();
637		return B_ERROR;
638	}
639
640	status_t result = fChannel->SendRequest(request,
641		IsATAPI() ? 0 : ATA_DEVICE_READY_REQUIRED);
642	if (result != B_OK) {
643		TRACE_ERROR("failed to send transfer request\n");
644		if (request->UseDMA())
645			fChannel->FinishDMA();
646		return result;
647	}
648
649	if (request->UseDMA()) {
650		fChannel->PrepareWaitingForInterrupt();
651		fChannel->StartDMA();
652
653		result = fChannel->WaitForInterrupt(request->Timeout());
654		status_t dmaResult = fChannel->FinishDMA();
655		if (result == B_OK && dmaResult == B_OK) {
656			fDMAFailures = 0;
657			request->CCB()->data_resid = 0;
658		} else {
659			if (dmaResult != B_OK) {
660				request->SetSense(SCSIS_KEY_HARDWARE_ERROR,
661					SCSIS_ASC_LUN_COM_FAILURE);
662				fDMAFailures++;
663				if (fDMAFailures >= ATA_MAX_DMA_FAILURES) {
664					TRACE_ALWAYS("disabling DMA after %u failures\n",
665						fDMAFailures);
666					fUseDMA = false;
667				}
668			} else {
669				// timeout
670				request->SetStatus(SCSI_CMD_TIMEOUT);
671			}
672		}
673	} else {
674		if (fChannel->Wait(ATA_STATUS_DATA_REQUEST, 0, ATA_CHECK_ERROR_BIT
675				| ATA_CHECK_DEVICE_FAULT, request->Timeout()) != B_OK) {
676			TRACE_ERROR("timeout waiting for device to request data\n");
677			request->SetStatus(SCSI_CMD_TIMEOUT);
678			return B_TIMED_OUT;
679		}
680
681		if (fChannel->ExecutePIOTransfer(request) != B_OK) {
682			TRACE_ERROR("executing pio transfer failed\n");
683			request->SetStatus(SCSI_SEQUENCE_FAIL);
684		}
685	}
686
687	return fChannel->FinishRequest(request, ATA_WAIT_FINISH
688		| ATA_DEVICE_READY_REQUIRED, ATA_ERROR_ALL);
689}
690
691
692status_t
693ATADevice::_FillTaskFile(ATARequest *request, uint64 address)
694{
695	// list of LBA48 opcodes
696	static const uint8 s48BitCommands[2][2] = {
697		{ ATA_COMMAND_READ_SECTORS_EXT, ATA_COMMAND_WRITE_SECTORS_EXT },
698		{ ATA_COMMAND_READ_DMA_EXT, ATA_COMMAND_WRITE_DMA_EXT }
699	};
700
701	// list of normal LBA opcodes
702	static const uint8 s28BitCommands[2][2] = {
703		{ ATA_COMMAND_READ_SECTORS, ATA_COMMAND_WRITE_SECTORS },
704		{ ATA_COMMAND_READ_DMA, ATA_COMMAND_WRITE_DMA }
705	};
706
707	uint32 sectorCount = *request->BytesLeft() / fBlockSize;
708	TRACE("about to transfer %lu sectors\n", sectorCount);
709
710	if (fUse48Bits
711		&& (address + sectorCount > 0xfffffff || sectorCount > 0x100)) {
712		// use LBA48 only if necessary
713		if (sectorCount > 0xffff) {
714			TRACE_ERROR("invalid sector count %lu\n", sectorCount);
715			request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST,
716				SCSIS_ASC_INV_CDB_FIELD);
717			return B_ERROR;
718		}
719
720		fRegisterMask = ATA_MASK_SECTOR_COUNT_48
721			| ATA_MASK_LBA_LOW_48
722			| ATA_MASK_LBA_MID_48
723			| ATA_MASK_LBA_HIGH_48;
724
725		fTaskFile.lba48.sector_count_0_7 = sectorCount & 0xff;
726		fTaskFile.lba48.sector_count_8_15 = (sectorCount >> 8) & 0xff;
727		fTaskFile.lba48.lba_0_7 = address & 0xff;
728		fTaskFile.lba48.lba_8_15 = (address >> 8) & 0xff;
729		fTaskFile.lba48.lba_16_23 = (address >> 16) & 0xff;
730		fTaskFile.lba48.lba_24_31 = (address >> 24) & 0xff;
731		fTaskFile.lba48.lba_32_39 = (address >> 32) & 0xff;
732		fTaskFile.lba48.lba_40_47 = (address >> 40) & 0xff;
733		fTaskFile.lba48.command = s48BitCommands[request->UseDMA()
734			? 1 : 0][request->IsWrite() ? 1 : 0];
735	} else {
736		// normal LBA
737		if (sectorCount > 0x100) {
738			TRACE_ERROR("invalid sector count %lu\n", sectorCount);
739			request->SetSense(SCSIS_KEY_ILLEGAL_REQUEST,
740				SCSIS_ASC_INV_CDB_FIELD);
741			return B_ERROR;
742		}
743
744		fRegisterMask = ATA_MASK_SECTOR_COUNT
745			| ATA_MASK_LBA_LOW
746			| ATA_MASK_LBA_MID
747			| ATA_MASK_LBA_HIGH
748			| ATA_MASK_DEVICE_HEAD;
749
750		fTaskFile.lba.sector_count = sectorCount & 0xff;
751		fTaskFile.lba.lba_0_7 = address & 0xff;
752		fTaskFile.lba.lba_8_15 = (address >> 8) & 0xff;
753		fTaskFile.lba.lba_16_23 = (address >> 16) & 0xff;
754		fTaskFile.lba.lba_24_27 = (address >> 24) & 0xf;
755		fTaskFile.lba.command = s28BitCommands[request->UseDMA()
756			? 1 : 0][request->IsWrite() ? 1 : 0];
757	}
758
759	return B_OK;
760}
761