- Timestamp:
- Nov 25, 2019 2:53:03 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 134990
- Location:
- trunk/src/VBox/Devices/PC/BIOS
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/ebda.h
r82163 r82180 261 261 extern uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf, 262 262 uint16_t header, uint32_t length, uint8_t inout, char __far *buffer); 263 extern uint16_t virtio_scsi_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf, 264 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer); 263 265 264 266 extern uint16_t ata_soft_reset(uint16_t device); -
trunk/src/VBox/Devices/PC/BIOS/eltorito.c
r76553 r82180 121 121 [DSK_TYPE_SCSI] = { scsi_cmd_packet }, 122 122 #endif 123 #ifdef VBOX_WITH_VIRTIO_SCSI 124 [DSK_TYPE_VIRTIO_SCSI] = { virtio_scsi_cmd_packet }, 125 #endif 123 126 }; 124 127 -
trunk/src/VBox/Devices/PC/BIOS/virtio.c
r82176 r82180 105 105 typedef struct 106 106 { 107 /** The descriptor table, using 4max. */108 virtio_q_desc_t aDescTbl[ 4];107 /** The descriptor table, using 5 max. */ 108 virtio_q_desc_t aDescTbl[5]; 109 109 /** Available ring. */ 110 110 virtio_q_avail_t AvailRing; … … 489 489 490 490 int virtio_scsi_cmd_data_in(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB, 491 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length) 491 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 492 uint16_t skip_b) 492 493 { 493 494 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed; 495 uint8_t idxDesc = 0; 494 496 495 497 _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr)); … … 503 505 504 506 /* Fill in the descriptors. */ 505 virtio->Queue.aDescTbl[0].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr); 506 virtio->Queue.aDescTbl[0].GCPhysBufHigh = 0; 507 virtio->Queue.aDescTbl[0].cbBuf = sizeof(virtio->ScsiReqHdr); 508 virtio->Queue.aDescTbl[0].fFlags = VIRTIO_Q_DESC_F_NEXT; 509 virtio->Queue.aDescTbl[0].idxNext = 1; 507 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr); 508 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0; 509 virtio->Queue.aDescTbl[idxDesc].cbBuf = sizeof(virtio->ScsiReqHdr); 510 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_NEXT; 511 virtio->Queue.aDescTbl[idxDesc].idxNext = 1; 512 idxDesc++; 510 513 511 514 /* No data out buffer, the status comes right after this in the next descriptor. */ 512 virtio->Queue.aDescTbl[1].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts); 513 virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0; 514 virtio->Queue.aDescTbl[1].cbBuf = sizeof(virtio->ScsiReqSts); 515 virtio->Queue.aDescTbl[1].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT; 516 virtio->Queue.aDescTbl[1].idxNext = 2; 517 518 virtio->Queue.aDescTbl[2].GCPhysBufLow = virtio_addr_to_phys(buffer); 519 virtio->Queue.aDescTbl[2].GCPhysBufHigh = 0; 520 virtio->Queue.aDescTbl[2].cbBuf = length; 521 virtio->Queue.aDescTbl[2].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */ 522 virtio->Queue.aDescTbl[2].idxNext = 0; 515 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts); 516 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0; 517 virtio->Queue.aDescTbl[idxDesc].cbBuf = sizeof(virtio->ScsiReqSts); 518 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT; 519 virtio->Queue.aDescTbl[idxDesc].idxNext = 2; 520 idxDesc++; 521 522 /* Prepend a sinkhole if data is skipped upfront. */ 523 if (skip_b) 524 { 525 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = 0; /* See ahci.c:sink_buf_phys */ 526 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0; 527 virtio->Queue.aDescTbl[idxDesc].cbBuf = skip_b; 528 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT; 529 virtio->Queue.aDescTbl[idxDesc].idxNext = idxDesc + 1; 530 idxDesc++; 531 } 532 533 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(buffer); 534 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0; 535 virtio->Queue.aDescTbl[idxDesc].cbBuf = length; 536 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */ 537 virtio->Queue.aDescTbl[idxDesc].idxNext = skip_a ? idxDesc + 1 : 0; 538 idxDesc++; 539 540 /* Append a sinkhole if data is skipped at the end. */ 541 if (skip_a) 542 { 543 virtio->Queue.aDescTbl[idxDesc - 1].fFlags |= VIRTIO_Q_DESC_F_NEXT; 544 virtio->Queue.aDescTbl[idxDesc - 1].idxNext = idxDesc; 545 546 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = 0; /* See ahci.c:sink_buf_phys */ 547 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0; 548 virtio->Queue.aDescTbl[idxDesc].cbBuf = skip_a; 549 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */ 550 virtio->Queue.aDescTbl[idxDesc].idxNext = 0; 551 } 523 552 524 553 /* Put it into the queue, the index is supposed to be free-running and clipped to the ring size … … 581 610 582 611 rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16, 583 bios_dsk->drqp.buffer, (count * 512L) );612 bios_dsk->drqp.buffer, (count * 512L), 0, 0); 584 613 585 614 if (!rc) … … 643 672 } 644 673 645 #if 0646 674 #define ATA_DATA_OUT 0x02 647 675 … … 653 681 * @param cmdlen Length of the CDB. 654 682 * @param cmdbuf The CDB buffer. 655 * @param beforeHow much to skip before reading into the provided data buffer.683 * @param skip_b How much to skip before reading into the provided data buffer. 656 684 * @param length How much to transfer. 657 685 * @param inout Read/Write direction indicator. 658 686 * @param buffer Data buffer to store the data from the device in. 659 687 */ 660 uint16_t scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,661 uint16_t before, uint32_t length, uint8_t inout, char __far *buffer)688 uint16_t virtio_scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf, 689 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer) 662 690 { 663 691 bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk; 664 uint32_t read_len; 665 uint8_t status, sizes; 666 uint16_t i; 667 uint16_t io_base; 692 uint8_t rc; 668 693 uint8_t target_id; 669 694 … … 674 699 } 675 700 701 /* The skip length must be even. */ 702 if (skip_b & 1) { 703 DBG_VIRTIO("%s: skip must be even (%04x)\n", __func__, skip_b); 704 return 1; 705 } 706 676 707 /* Convert to SCSI specific device number. */ 677 708 device_id = VBOX_GET_SCSI_DEVICE(device_id); … … 683 714 bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz); 684 715 685 cmdlen -= 2; /* ATAPI uses 12-byte command packets for a READ 10. */ 686 687 io_base = bios_dsk->scsidev[device_id].io_base; 716 high_bits_save(bios_dsk->virtio_seg :> 0); 688 717 target_id = bios_dsk->scsidev[device_id].target_id; 689 718 690 /* Wait until the adapter is ready. */ 691 do 692 status = inb(io_base + VBSCSI_REGISTER_STATUS); 693 while (status & VBSCSI_BUSY); 694 695 /* On the SCSI level, we have to transfer whole sectors. */ 696 /* NB: With proper residual length support, this should not be necessary; we should 697 * be able to avoid transferring the 'after' part of the sector. 698 */ 699 read_len = length + before + bios_dsk->drqp.skip_a; 700 701 sizes = (((read_len) >> 12) & 0xF0) | cmdlen; 702 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 703 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */ 704 outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write the CDB size. */ 705 outb(io_base + VBSCSI_REGISTER_COMMAND, read_len); /* Write the buffer size. */ 706 outb(io_base + VBSCSI_REGISTER_COMMAND, (read_len) >> 8); 707 for (i = 0; i < cmdlen; i++) /* Write the CDB. */ 708 outb(io_base + VBSCSI_REGISTER_COMMAND, cmdbuf[i]); 709 710 /* Now wait for the command to complete. */ 711 do 712 status = inb(io_base + VBSCSI_REGISTER_STATUS); 713 while (status & VBSCSI_BUSY); 714 715 /* If any error occurred, inform the caller and don't bother reading the data. */ 716 if (status & VBSCSI_ERROR) { 717 outb(io_base + VBSCSI_REGISTER_RESET, 0); 718 719 status = inb(io_base + VBSCSI_REGISTER_DEVSTAT); 720 DBG_SCSI("%s: read failed, device status %02X\n", __func__, status); 721 return 3; 722 } 723 724 /* Transfer the data read from the device. */ 725 726 if (before) /* If necessary, throw away data which needs to be skipped. */ 727 insb_discard(before, io_base + VBSCSI_REGISTER_DATA_IN); 728 729 bios_dsk->drqp.trsfbytes = length; 730 731 /* The requested length may be exactly 64K or more, which needs 732 * a bit of care when we're using 16-bit 'rep ins'. 733 */ 734 while (length > 32768) { 735 DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer)); 736 rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN); 737 length -= 32768; 738 buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer); 739 } 740 741 DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer)); 742 rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN); 743 744 if (bios_dsk->drqp.skip_a) /* If necessary, throw away more data. */ 745 insb_discard(bios_dsk->drqp.skip_a, io_base + VBSCSI_REGISTER_DATA_IN); 746 747 return 0; 748 } 749 #endif 719 bios_dsk->drqp.lba = length << 8; /// @todo xfer length limit 720 bios_dsk->drqp.buffer = buffer; 721 bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz; 722 723 DBG_VIRTIO("%s: reading %u bytes, device %d, target %d\n", __func__, 724 length, device_id, bios_dsk->scsidev[device_id].target_id); 725 726 rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)cmdbuf, cmdlen, 727 bios_dsk->drqp.buffer, length, skip_b, bios_dsk->drqp.skip_a); 728 if (!rc) 729 bios_dsk->drqp.trsfbytes = length; 730 731 DBG_VIRTIO("%s: transferred %u bytes\n", __func__, length); 732 high_bits_restore(bios_dsk->virtio_seg :> 0); 733 734 return rc; 735 } 750 736 751 737 static int virtio_scsi_detect_devices(virtio_t __far *virtio) … … 771 757 aCDB[5] = 0; 772 758 773 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5); 759 _fmemset(buffer, 0, sizeof(buffer)); 760 761 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5, 0, 0); 774 762 if (rc != 0) 775 763 BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__); … … 798 786 aCDB[13] = 32; /* Allocation length. */ 799 787 800 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32 );788 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32, 0, 0); 801 789 if (rc != 0) 802 790 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__); … … 922 910 } 923 911 } 924 #if 0925 912 else if ( ((buffer[0] & 0xe0) == 0) 926 913 && ((buffer[0] & 0x1f) == 0x05)) … … 951 938 devcount_scsi++; 952 939 } 953 #endif954 940 else 955 941 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
Note:
See TracChangeset
for help on using the changeset viewer.