X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fata.h;h=d79e0123662b7ddaadea3cbfc16ae0e1fa720ab3;hb=c8e5b4d78f746b7ac5de1a19689ba9aa2d7e3db3;hp=dd1c4b7ba10e504193a04da96c4c830bb89272d1;hpb=db03a1fef60b6d90c02a65369292a57833a7824b;p=palacios.git diff --git a/palacios/src/devices/ata.h b/palacios/src/devices/ata.h index dd1c4b7..d79e012 100644 --- a/palacios/src/devices/ata.h +++ b/palacios/src/devices/ata.h @@ -23,6 +23,9 @@ #define MAX_MULT_SECTORS 255 + + + static void ata_identify_device(struct ide_drive * drive) { struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf); const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0"; @@ -55,13 +58,14 @@ static void ata_identify_device(struct ide_drive * drive) { memcpy(drive_id->firmware_rev, firmware, strlen(firmware)); memcpy(drive_id->model_num, drive->model, 40); - // 32 bits access + // 32 bits access for PIO supported drive_id->dword_io = 1; // enable DMA access - // PAD disable DMA capability - drive_id->dma_enable = 0; // 1; + // We want guest to assume UDMA5 + // but any DMA model looks the same to the guest + drive_id->dma_enable = 1; // enable LBA access drive_id->lba_enable = 1; @@ -88,7 +92,9 @@ static void ata_identify_device(struct ide_drive * drive) { drive_id->buf[63] = 0x0007; - // PAD: Support PIO mode 0 + // We wll support PIO mode 0 + // Maybe revisit this later to allow advanced modes + // We really want the guest to use DMA drive_id->buf[64] = 0x0001; // PIO // MWDMA transfer min cycle time @@ -104,6 +110,7 @@ static void ata_identify_device(struct ide_drive * drive) { drive_id->buf[72] = 30; // faked // queue depth set to one + // We should not expect queued DMAs // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6 @@ -113,8 +120,8 @@ static void ata_identify_device(struct ide_drive * drive) { // No special features supported - // PAD: Disable ultra DMA capability - //drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported; + // Pretend drive is already autoconfed to UDMA5 + drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported; } @@ -163,55 +170,68 @@ static int ata_write(struct ide_internal * ide, struct ide_channel * channel, ui } - -static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba) { +// +// Grand unified conversion for various addressing modes: +// +// CHS => 64 bit LBA (8 bit sector count) +// LBA28 => 64 bit LBA (8 bit sector count) +// LBA48 => 64 bit LBA (16 bit sector count) +static int ata_get_lba_and_size(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba, uint64_t *num_sects) { struct ide_drive * drive = get_selected_drive(channel); - // The if the sector count == 0 then read 256 sectors (cast up to handle that value) - uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count; - - if (is_lba_enabled(channel)) { - union { - uint32_t addr; - uint8_t buf[4]; - } __attribute__((packed)) lba_addr; - - /* LBA addr bits: - 0-8: sector number reg (drive->lba0) - 8-16: low cylinder reg (drive->lba1) - 16-24: high cylinder reg (drive->lba2) - 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num) - */ - - - lba_addr.buf[0] = drive->lba0; - lba_addr.buf[1] = drive->lba1; - lba_addr.buf[2] = drive->lba2; - lba_addr.buf[3] = channel->drive_head.lba3; - - *lba = lba_addr.addr; - - PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba0=%u (sect), lba1=%u (cyllow), lba2=%u (cylhigh), lba3=%d (head) => lba=%llu\n", drive->lba0, drive->lba1, drive->lba2, channel->drive_head.lba3, *lba); + if (is_lba48(channel)) { + *num_sects = drive->lba48.sector_count; + *lba = drive->lba48.lba; + PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba48: lba=%llu, num_sects=%llu\n",*lba,*num_sects); } else { - // we are in CHS mode.... - - *lba = - (drive->cylinder * drive->num_heads + - channel->drive_head.head_num) * drive->num_sectors + - // sector number is 1 based - (drive->sector_num - 1); + // LBA48 or CHS + // The if the sector count == 0 then read 256 sectors (cast up to handle that value) + *num_sects = (drive->sector_count == 0) ? 256 : drive->sector_count; - - PrintDebug(VM_NONE,VCORE_NONE,"get_lba: Huh, 1995 has returned - CHS (%u,%u,%u) addressing on drive of (%u,%u,%u) translated as %llu....\n", - drive->cylinder, channel->drive_head.head_num, drive->sector_num, - drive->num_cylinders, drive->num_heads, drive->num_sectors, *lba ); + if (is_lba28(channel)) { + union { + uint32_t addr; + uint8_t buf[4]; + } __attribute__((packed)) lba_addr; + + /* LBA addr bits: + 0-8: sector number reg (drive->lba0) + 8-16: low cylinder reg (drive->lba1) + 16-24: high cylinder reg (drive->lba2) + 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num) + */ + + + lba_addr.buf[0] = drive->lba0; + lba_addr.buf[1] = drive->lba1; + lba_addr.buf[2] = drive->lba2; + lba_addr.buf[3] = channel->drive_head.lba3; + + *lba = lba_addr.addr; + + PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba28: lba0=%u (sect), lba1=%u (cyllow), lba2=%u (cylhigh), lba3=%d (head) => lba=%llu numsects=%llu\n", drive->lba0, drive->lba1, drive->lba2, channel->drive_head.lba3, *lba, *num_sects); + + } else { + // we are in CHS mode.... + + *lba = + (drive->cylinder * drive->num_heads + + channel->drive_head.head_num) * drive->num_sectors + + // sector number is 1 based + (drive->sector_num - 1); + + + PrintDebug(VM_NONE,VCORE_NONE,"get_lba: Huh, 1995 has returned - CHS (%u,%u,%u) addressing on drive of (%u,%u,%u) translated as lba=%llu num_sects=%llu....\n", + drive->cylinder, channel->drive_head.head_num, drive->sector_num, + drive->num_cylinders, drive->num_heads, drive->num_sectors, *lba,*num_sects ); + } } - if ((*lba + sect_cnt) > + if ((*lba + *num_sects) > drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) { - PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%llu) (sect_cnt=%u) (ReadEnd=%llu) (capacity=%llu)\n", - *lba, sect_cnt, - *lba + (sect_cnt * HD_SECTOR_SIZE), + PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%llu) (num_sects=%llu) (ReadEnd=%llu) (capacity=%llu)\n", + *lba, *num_sects, + *lba + (*num_sects * HD_SECTOR_SIZE), drive->ops->get_capacity(drive->private_data)); return -1; } @@ -220,18 +240,17 @@ static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel, } -// 28 bit LBA static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * channel) { + uint64_t sect_cnt; struct ide_drive * drive = get_selected_drive(channel); - uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count; - if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) { - PrintError(VM_NONE,VCORE_NONE,"Cannot get lba\n"); + if (ata_get_lba_and_size(ide, channel, &(drive->current_lba), §_cnt ) == -1) { + PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n"); ide_abort_command(ide, channel); return 0; } - PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%u\n", drive->current_lba, sect_cnt); + PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%llu\n", drive->current_lba, sect_cnt); drive->transfer_length = sect_cnt * HD_SECTOR_SIZE ; drive->transfer_index = 0; @@ -247,14 +266,13 @@ static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * ch } -// 28 bit LBA +// 28 bit LBA or CHS static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * channel) { + uint64_t sect_cnt; struct ide_drive * drive = get_selected_drive(channel); - // The if the sector count == 0 then read 256 sectors (cast up to handle that value) - uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count; - if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) { - PrintError(VM_NONE,VCORE_NONE,"Cannot get lba\n"); + if (ata_get_lba_and_size(ide, channel, &(drive->current_lba),§_cnt) == -1) { + PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n"); ide_abort_command(ide, channel); return 0; } @@ -282,17 +300,6 @@ static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * cha } -// 48 bit LBA -static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel * channel) { - //struct ide_drive * drive = get_selected_drive(channel); - // The if the sector count == 0 then read 256 sectors (cast up to handle that value) - //uint32_t sector_count = (drive->sector_count == 0) ? 256 : drive->sector_count; - - PrintError(VM_NONE, VCORE_NONE, "Extended Sector read not implemented\n"); - - return -1; -} - /* ATA COMMANDS as per */ /* ACS-2 T13/2015-D Table B.2 Command codes */ #define ATA_NOP 0x00