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