X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fata.h;h=cb0193e965d29ad5e3e1cfeb820e43076a4e40d2;hp=b759f0bfc2205a4c4d491d7ce1220ef149ddffcb;hb=0121a4503305424096e2b5c5bd3b6c3af2d813e5;hpb=6661dd1d2aa547ae248e816dcd4201bcbcb7fee0 diff --git a/palacios/src/devices/ata.h b/palacios/src/devices/ata.h index b759f0b..cb0193e 100644 --- a/palacios/src/devices/ata.h +++ b/palacios/src/devices/ata.h @@ -17,6 +17,8 @@ * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ +#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); @@ -39,11 +41,11 @@ static void ata_identify_device(struct ide_drive * drive) { drive_id->cdrom_flag = 0; // Make it the simplest drive possible (1 head, 1 cyl, 1 sect/track) - drive_id->num_cylinders = 1; - drive_id->num_heads = 1; - drive_id->bytes_per_track = IDE_SECTOR_SIZE; - drive_id->bytes_per_sector = IDE_SECTOR_SIZE; - drive_id->sectors_per_track = 1; + drive_id->num_cylinders = drive->num_cylinders; + drive_id->num_heads = drive->num_heads; + drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE; + drive_id->bytes_per_sector = HD_SECTOR_SIZE; + drive_id->sectors_per_track = drive->num_sectors; // These buffers do not contain a terminating "\0" @@ -54,6 +56,7 @@ static void ata_identify_device(struct ide_drive * drive) { // 32 bits access drive_id->dword_io = 1; + // enable DMA access drive_id->dma_enable = 1; @@ -61,19 +64,26 @@ static void ata_identify_device(struct ide_drive * drive) { drive_id->lba_enable = 1; // Drive Capacity (28 bit LBA) - drive_id->lba_capacity = drive->hd_ops->get_capacity(drive->private_data); + drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE; // Drive Capacity (48 bit LBA) - drive_id->lba_capacity_2 = drive->hd_ops->get_capacity(drive->private_data); + drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE; + + + // lower byte is the maximum multiple sector size... + drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS; + - drive_id->rw_multiples = 0x80ff; // words 64-70, 54-58 valid drive_id->field_valid = 0x0007; // DMA + pkg cmd valid + // copied from CFA540A - drive_id->buf[63] = 0x0103; // variable (DMA stuff) + // drive_id->buf[63] = 0x0103; // variable (DMA stuff) //drive_id->buf[63] = 0x0000; // variable (DMA stuff) + drive_id->buf[63] = 0x0007; + // drive_id->buf[64] = 0x0001; // PIO drive_id->buf[65] = 0x00b4; @@ -87,14 +97,16 @@ static void ata_identify_device(struct ide_drive * drive) { // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6 + drive_id->buf[83] |= 0x0400; // supports 48 bit LBA drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported; + } -static int ata_read(struct vm_device * dev, struct ide_channel * channel) { +static int ata_read(struct vm_device * dev, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) { struct ide_drive * drive = get_selected_drive(channel); if (drive->hd_state.accessed == 0) { @@ -102,7 +114,9 @@ static int ata_read(struct vm_device * dev, struct ide_channel * channel) { drive->hd_state.accessed = 1; } - int ret = drive->hd_ops->read(drive->data_buf, 1, drive->current_lba, drive->private_data); + PrintDebug("Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt); + + int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data); if (ret == -1) { PrintError("IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba)); @@ -110,12 +124,30 @@ static int ata_read(struct vm_device * dev, struct ide_channel * channel) { } return 0; + + + } +static int ata_write(struct vm_device * dev, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) { + struct ide_drive * drive = get_selected_drive(channel); -// 28 bit LBA -static int ata_read_sectors(struct vm_device * dev, struct ide_channel * channel) { + PrintDebug("Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt); + + int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data); + + if (ret == -1) { + PrintError("IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba)); + return -1; + } + + return 0; +} + + + +static int ata_get_lba(struct vm_device * dev, struct ide_channel * channel, uint64_t * lba) { 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; @@ -137,28 +169,39 @@ static int ata_read_sectors(struct vm_device * dev, struct ide_channel * channel lba_addr.buf[2] = drive->lba2; lba_addr.buf[3] = channel->drive_head.lba3; - PrintDebug("LBA Address %d\n", drive->lba0); - PrintDebug("sector_num %d\n", drive->sector_num); - - if (lba_addr.addr + (sect_cnt * IDE_SECTOR_SIZE) > - drive->hd_ops->get_capacity(drive->private_data)) { + if ((lba_addr.addr + sect_cnt) > + drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) { PrintError("IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n", lba_addr.addr, sect_cnt, - lba_addr.addr + (sect_cnt * IDE_SECTOR_SIZE), - (void *)(addr_t)(drive->hd_ops->get_capacity(drive->private_data))); + lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE), + (void *)(addr_t)(drive->ops->get_capacity(drive->private_data))); + return -1; + } + + *lba = lba_addr.addr; + return 0; +} + + +// 28 bit LBA +static int ata_read_sectors(struct vm_device * dev, 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 sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count; + + if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) { ide_abort_command(dev, channel); return 0; } - drive->current_lba = lba_addr.addr; - if (ata_read(dev, channel) == -1) { + if (ata_read(dev, channel, drive->data_buf, 1) == -1) { PrintError("Could not read disk sector\n"); return -1; } - drive->transfer_length = sect_cnt * IDE_SECTOR_SIZE; + drive->transfer_length = sect_cnt * HD_SECTOR_SIZE; drive->transfer_index = 0; channel->status.busy = 0;