Changes in uspace/srv/bd/ata_bd/ata_bd.c [47b7006:aa893e0] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/ata_bd/ata_bd.c
r47b7006 raa893e0 51 51 #include <libarch/ddi.h> 52 52 #include <ddi.h> 53 #include <ipc/ipc.h> 53 54 #include <ipc/bd.h> 54 55 #include <async.h> 55 56 #include <as.h> 56 57 #include <fibril_synch.h> 58 #include <stdint.h> 57 59 #include <str.h> 58 60 #include <devmap.h> … … 61 63 #include <errno.h> 62 64 #include <bool.h> 65 #include <byteorder.h> 63 66 #include <task.h> 64 67 #include <macros.h> … … 73 76 #define LEGACY_CTLS 4 74 77 75 /** Physical block size. Should be always 512. */ 76 static const size_t block_size = 512; 78 /** 79 * Size of data returned from Identify Device or Identify Packet Device 80 * command. 81 */ 82 static const size_t identify_data_size = 512; 77 83 78 84 /** Size of the communication area. */ … … 105 111 static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt, 106 112 const void *buf); 107 static int ata_ bd_read_block(int disk_id, uint64_t ba, size_t cnt,113 static int ata_rcmd_read(int disk_id, uint64_t ba, size_t cnt, 108 114 void *buf); 109 static int ata_ bd_write_block(int disk_id, uint64_t ba, size_t cnt,115 static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt, 110 116 const void *buf); 111 117 static int disk_init(disk_t *d, int disk_id); 112 118 static int drive_identify(int drive_id, void *buf); 119 static int identify_pkt_dev(int dev_idx, void *buf); 120 static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size, 121 void *obuf, size_t obuf_size); 122 static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size); 123 static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt, 124 void *obuf, size_t obuf_size); 113 125 static void disk_print_summary(disk_t *d); 114 126 static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc); … … 203 215 printf("%s: ", d->model); 204 216 205 switch (d->amode) { 206 case am_chs: 207 printf("CHS %u cylinders, %u heads, %u sectors", 208 disk->geom.cylinders, disk->geom.heads, disk->geom.sectors); 209 break; 210 case am_lba28: 211 printf("LBA-28"); 212 break; 213 case am_lba48: 214 printf("LBA-48"); 215 break; 217 if (d->dev_type == ata_reg_dev) { 218 switch (d->amode) { 219 case am_chs: 220 printf("CHS %u cylinders, %u heads, %u sectors", 221 disk->geom.cylinders, disk->geom.heads, 222 disk->geom.sectors); 223 break; 224 case am_lba28: 225 printf("LBA-28"); 226 break; 227 case am_lba48: 228 printf("LBA-48"); 229 break; 230 } 231 } else { 232 printf("PACKET"); 216 233 } 217 234 … … 265 282 sysarg_t method; 266 283 devmap_handle_t dh; 267 unsignedint flags;284 int flags; 268 285 int retval; 269 286 uint64_t ba; … … 281 298 282 299 if (disk_id < 0 || disk[disk_id].present == false) { 283 async_answer_0(iid, EINVAL);300 ipc_answer_0(iid, EINVAL); 284 301 return; 285 302 } 286 303 287 304 /* Answer the IPC_M_CONNECT_ME_TO call. */ 288 async_answer_0(iid, EOK);305 ipc_answer_0(iid, EOK); 289 306 290 307 if (!async_share_out_receive(&callid, &comm_size, &flags)) { 291 async_answer_0(callid, EHANGUP);308 ipc_answer_0(callid, EHANGUP); 292 309 return; 293 310 } … … 295 312 fs_va = as_get_mappable_page(comm_size); 296 313 if (fs_va == NULL) { 297 async_answer_0(callid, EHANGUP);314 ipc_answer_0(callid, EHANGUP); 298 315 return; 299 316 } … … 307 324 case IPC_M_PHONE_HUNGUP: 308 325 /* The other side has hung up. */ 309 async_answer_0(callid, EOK);326 ipc_answer_0(callid, EOK); 310 327 return; 311 328 case BD_READ_BLOCKS: … … 313 330 IPC_GET_ARG2(call)); 314 331 cnt = IPC_GET_ARG3(call); 315 if (cnt * block_size > comm_size) {332 if (cnt * disk[disk_id].block_size > comm_size) { 316 333 retval = ELIMIT; 317 334 break; … … 323 340 IPC_GET_ARG2(call)); 324 341 cnt = IPC_GET_ARG3(call); 325 if (cnt * block_size > comm_size) {342 if (cnt * disk[disk_id].block_size > comm_size) { 326 343 retval = ELIMIT; 327 344 break; … … 330 347 break; 331 348 case BD_GET_BLOCK_SIZE: 332 async_answer_1(callid, EOK,block_size);349 ipc_answer_1(callid, EOK, disk[disk_id].block_size); 333 350 continue; 334 351 case BD_GET_NUM_BLOCKS: 335 async_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),352 ipc_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks), 336 353 UPPER32(disk[disk_id].blocks)); 337 354 continue; … … 340 357 break; 341 358 } 342 async_answer_0(callid, retval);359 ipc_answer_0(callid, retval); 343 360 } 344 361 } … … 353 370 identify_data_t idata; 354 371 uint8_t model[40]; 372 ata_inquiry_data_t inq_data; 355 373 uint16_t w; 356 374 uint8_t c; … … 359 377 unsigned i; 360 378 379 d->present = false; 380 fibril_mutex_initialize(&d->lock); 381 382 /* Try identify command. */ 361 383 rc = drive_identify(disk_id, &idata); 362 if (rc != EOK) { 363 d->present = false; 364 return rc; 365 } 366 367 if ((idata.caps & cap_lba) == 0) { 384 if (rc == EOK) { 385 /* Success. It's a register (non-packet) device. */ 386 printf("ATA register-only device found.\n"); 387 d->dev_type = ata_reg_dev; 388 } else if (rc == EIO) { 389 /* 390 * There is something, but not a register device. 391 * It could be a packet device. 392 */ 393 rc = identify_pkt_dev(disk_id, &idata); 394 if (rc == EOK) { 395 /* We have a packet device. */ 396 d->dev_type = ata_pkt_dev; 397 } else { 398 /* Nope. Something's there, but not recognized. */ 399 return EIO; 400 } 401 } else { 402 /* Operation timed out. That means there is no device there. */ 403 return EIO; 404 } 405 406 printf("device caps: 0x%04x\n", idata.caps); 407 if (d->dev_type == ata_pkt_dev) { 408 /* Packet device */ 409 d->amode = 0; 410 411 d->geom.cylinders = 0; 412 d->geom.heads = 0; 413 d->geom.sectors = 0; 414 415 d->blocks = 0; 416 } else if ((idata.caps & rd_cap_lba) == 0) { 368 417 /* Device only supports CHS addressing. */ 369 418 d->amode = am_chs; … … 422 471 d->model[pos] = '\0'; 423 472 473 if (d->dev_type == ata_pkt_dev) { 474 /* Send inquiry. */ 475 rc = ata_pcmd_inquiry(0, &inq_data, sizeof(inq_data)); 476 if (rc != EOK) { 477 printf("Device inquiry failed.\n"); 478 d->present = false; 479 return EIO; 480 } 481 482 /* Check device type. */ 483 if (INQUIRY_PDEV_TYPE(inq_data.pdev_type) != PDEV_TYPE_CDROM) 484 printf("Warning: Peripheral device type is not CD-ROM.\n"); 485 486 /* Assume 2k block size for now. */ 487 d->block_size = 2048; 488 } else { 489 /* Assume register Read always uses 512-byte blocks. */ 490 d->block_size = 512; 491 } 492 424 493 d->present = true; 425 fibril_mutex_initialize(&d->lock);426 427 494 return EOK; 428 495 } … … 435 502 436 503 while (cnt > 0) { 437 rc = ata_bd_read_block(disk_id, ba, 1, buf); 504 if (disk[disk_id].dev_type == ata_reg_dev) 505 rc = ata_rcmd_read(disk_id, ba, 1, buf); 506 else 507 rc = ata_pcmd_read_12(disk_id, ba, 1, buf, 508 disk[disk_id].block_size); 509 438 510 if (rc != EOK) 439 511 return rc; … … 441 513 ++ba; 442 514 --cnt; 443 buf += block_size;515 buf += disk[disk_id].block_size; 444 516 } 445 517 … … 453 525 int rc; 454 526 527 if (disk[disk_id].dev_type != ata_reg_dev) 528 return ENOTSUP; 529 455 530 while (cnt > 0) { 456 rc = ata_ bd_write_block(disk_id, ba, 1, buf);531 rc = ata_rcmd_write(disk_id, ba, 1, buf); 457 532 if (rc != EOK) 458 533 return rc; … … 460 535 ++ba; 461 536 --cnt; 462 buf += block_size;537 buf += disk[disk_id].block_size; 463 538 } 464 539 … … 473 548 * @param disk_id Device ID, 0 or 1. 474 549 * @param buf Pointer to a 512-byte buffer. 550 * 551 * @return ETIMEOUT on timeout (this can mean the device is 552 * not present). EIO if device responds with error. 475 553 */ 476 554 static int drive_identify(int disk_id, void *buf) … … 484 562 485 563 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 486 return E IO;564 return ETIMEOUT; 487 565 488 566 pio_write_8(&cmd->drive_head, drv_head); … … 493 571 */ 494 572 if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 495 return E IO;573 return ETIMEOUT; 496 574 497 575 pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); 498 576 499 577 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) 500 return E IO;578 return ETIMEOUT; 501 579 502 580 /* Read data from the disk buffer. */ 503 581 504 582 if ((status & SR_DRQ) != 0) { 505 for (i = 0; i < block_size / 2; i++) {583 for (i = 0; i < identify_data_size / 2; i++) { 506 584 data = pio_read_16(&cmd->data_port); 507 585 ((uint16_t *) buf)[i] = data; … … 509 587 } 510 588 589 if ((status & SR_ERR) != 0) { 590 return EIO; 591 } 592 593 return EOK; 594 } 595 596 /** Issue Identify Packet Device command. 597 * 598 * Reads @c identify data into the provided buffer. This is used to detect 599 * whether an ATAPI device is present and if so, to determine its parameters. 600 * 601 * @param dev_idx Device index, 0 or 1. 602 * @param buf Pointer to a 512-byte buffer. 603 */ 604 static int identify_pkt_dev(int dev_idx, void *buf) 605 { 606 uint16_t data; 607 uint8_t status; 608 uint8_t drv_head; 609 size_t i; 610 611 drv_head = ((dev_idx != 0) ? DHR_DRV : 0); 612 613 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 614 return EIO; 615 616 pio_write_8(&cmd->drive_head, drv_head); 617 618 /* For ATAPI commands we do not need to wait for DRDY. */ 619 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) 620 return EIO; 621 622 pio_write_8(&cmd->command, CMD_IDENTIFY_PKT_DEV); 623 624 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) 625 return EIO; 626 627 /* Read data from the device buffer. */ 628 629 if ((status & SR_DRQ) != 0) { 630 for (i = 0; i < identify_data_size / 2; i++) { 631 data = pio_read_16(&cmd->data_port); 632 ((uint16_t *) buf)[i] = data; 633 } 634 } 635 511 636 if ((status & SR_ERR) != 0) 512 637 return EIO; 638 639 return EOK; 640 } 641 642 /** Issue packet command (i. e. write a command packet to the device). 643 * 644 * Only data-in commands are supported (e.g. inquiry, read). 645 * 646 * @param dev_idx Device index (0 or 1) 647 * @param obuf Buffer for storing data read from device 648 * @param obuf_size Size of obuf in bytes 649 * 650 * @return EOK on success, EIO on error. 651 */ 652 static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size, 653 void *obuf, size_t obuf_size) 654 { 655 size_t i; 656 uint8_t status; 657 uint8_t drv_head; 658 disk_t *d; 659 size_t data_size; 660 uint16_t val; 661 662 d = &disk[dev_idx]; 663 fibril_mutex_lock(&d->lock); 664 665 /* New value for Drive/Head register */ 666 drv_head = 667 ((dev_idx != 0) ? DHR_DRV : 0); 668 669 if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) { 670 fibril_mutex_unlock(&d->lock); 671 return EIO; 672 } 673 674 pio_write_8(&cmd->drive_head, drv_head); 675 676 if (wait_status(0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) { 677 fibril_mutex_unlock(&d->lock); 678 return EIO; 679 } 680 681 /* Byte count <- max. number of bytes we can read in one transfer. */ 682 pio_write_8(&cmd->cylinder_low, 0xfe); 683 pio_write_8(&cmd->cylinder_high, 0xff); 684 685 pio_write_8(&cmd->command, CMD_PACKET); 686 687 if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 688 fibril_mutex_unlock(&d->lock); 689 return EIO; 690 } 691 692 /* Write command packet. */ 693 for (i = 0; i < (cpkt_size + 1) / 2; i++) 694 pio_write_16(&cmd->data_port, ((uint16_t *) cpkt)[i]); 695 696 if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 697 fibril_mutex_unlock(&d->lock); 698 return EIO; 699 } 700 701 if ((status & SR_DRQ) == 0) { 702 fibril_mutex_unlock(&d->lock); 703 return EIO; 704 } 705 706 /* Read byte count. */ 707 data_size = (uint16_t) pio_read_8(&cmd->cylinder_low) + 708 ((uint16_t) pio_read_8(&cmd->cylinder_high) << 8); 709 710 /* Check whether data fits into output buffer. */ 711 if (data_size > obuf_size) { 712 /* Output buffer is too small to store data. */ 713 fibril_mutex_unlock(&d->lock); 714 return EIO; 715 } 716 717 /* Read data from the device buffer. */ 718 for (i = 0; i < (data_size + 1) / 2; i++) { 719 val = pio_read_16(&cmd->data_port); 720 ((uint16_t *) obuf)[i] = val; 721 } 722 723 if (status & SR_ERR) { 724 fibril_mutex_unlock(&d->lock); 725 return EIO; 726 } 727 728 fibril_mutex_unlock(&d->lock); 729 730 return EOK; 731 } 732 733 /** Issue ATAPI Inquiry. 734 * 735 * @param dev_idx Device index (0 or 1) 736 * @param obuf Buffer for storing inquiry data read from device 737 * @param obuf_size Size of obuf in bytes 738 * 739 * @return EOK on success, EIO on error. 740 */ 741 static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size) 742 { 743 ata_pcmd_inquiry_t cp; 744 int rc; 745 746 memset(&cp, 0, sizeof(cp)); 747 748 cp.opcode = PCMD_INQUIRY; 749 cp.alloc_len = min(obuf_size, 0xff); /* Allocation length */ 750 751 rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size); 752 if (rc != EOK) 753 return rc; 754 755 return EOK; 756 } 757 758 /** Issue ATAPI read(12) command. 759 * 760 * Output buffer must be large enough to hold the data, otherwise the 761 * function will fail. 762 * 763 * @param dev_idx Device index (0 or 1) 764 * @param ba Starting block address 765 * @param cnt Number of blocks to read 766 * @param obuf Buffer for storing inquiry data read from device 767 * @param obuf_size Size of obuf in bytes 768 * 769 * @return EOK on success, EIO on error. 770 */ 771 static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt, 772 void *obuf, size_t obuf_size) 773 { 774 ata_pcmd_read_12_t cp; 775 int rc; 776 777 if (ba > UINT32_MAX) 778 return EINVAL; 779 780 memset(&cp, 0, sizeof(cp)); 781 782 cp.opcode = PCMD_READ_12; 783 cp.ba = host2uint32_t_be(ba); 784 cp.nblocks = host2uint32_t_be(cnt); 785 786 rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size); 787 if (rc != EOK) 788 return rc; 513 789 514 790 return EOK; … … 524 800 * @return EOK on success, EIO on error. 525 801 */ 526 static int ata_ bd_read_block(int disk_id, uint64_t ba, size_t blk_cnt,802 static int ata_rcmd_read(int disk_id, uint64_t ba, size_t blk_cnt, 527 803 void *buf) 528 804 { … … 579 855 /* Read data from the device buffer. */ 580 856 581 for (i = 0; i < block_size / 2; i++) {857 for (i = 0; i < disk[disk_id].block_size / 2; i++) { 582 858 data = pio_read_16(&cmd->data_port); 583 859 ((uint16_t *) buf)[i] = data; … … 601 877 * @return EOK on success, EIO on error. 602 878 */ 603 static int ata_ bd_write_block(int disk_id, uint64_t ba, size_t cnt,879 static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt, 604 880 const void *buf) 605 881 { … … 655 931 /* Write data to the device buffer. */ 656 932 657 for (i = 0; i < block_size / 2; i++) {933 for (i = 0; i < disk[disk_id].block_size / 2; i++) { 658 934 pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); 659 935 }
Note:
See TracChangeset
for help on using the changeset viewer.