From: Jack Lange Date: Fri, 3 Apr 2009 18:07:43 +0000 (-0500) Subject: Added intial cut at IDE disk support X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=4659d019e2f65b9397e2289a9add28a3adf47cf8 Added intial cut at IDE disk support --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index f243949..46fcc40 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -331,6 +331,7 @@ DEVICES_OBJS := \ devices/para_net.o \ devices/ide.o \ devices/ram_cd.o \ + devices/ram_hd.o \ # devices/cdrom.o \ # devices/ramdisk.o \ diff --git a/palacios/include/devices/ide.h b/palacios/include/devices/ide.h index 4dce588..e0356b2 100644 --- a/palacios/include/devices/ide.h +++ b/palacios/include/devices/ide.h @@ -24,6 +24,9 @@ #include +#define ATAPI_BLOCK_SIZE 2048 +#define IDE_SECTOR_SIZE 512 + typedef enum {IDE_DISK, IDE_CDROM, IDE_NONE} v3_ide_dev_type_t; struct v3_ide_cd_ops { @@ -35,7 +38,9 @@ struct v3_ide_cd_ops { struct v3_ide_hd_ops { - + uint32_t (*get_capacity)(void * private_data); + // Reads always operate on 2048 byte blocks + int (*read)(uint8_t * buf, int count, int lba, void * private_data); }; diff --git a/palacios/include/devices/ram_hd.h b/palacios/include/devices/ram_hd.h new file mode 100644 index 0000000..77adf3e --- /dev/null +++ b/palacios/include/devices/ram_hd.h @@ -0,0 +1,36 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __DEVICES_RAM_HD_H__ +#define __DEVICES_RAM_HD_H__ + +#ifdef __V3VEE__ + +#include + + +struct vm_device * v3_create_ram_hd(struct vm_device * ide, + uint_t bus, uint_t drive, + addr_t ramdisk, uint32_t size); + + + +#endif + +#endif diff --git a/palacios/src/devices/atapi.h b/palacios/src/devices/atapi.h index 3d98a75..3407101 100644 --- a/palacios/src/devices/atapi.h +++ b/palacios/src/devices/atapi.h @@ -18,7 +18,6 @@ */ #define ATAPI_PACKET_SIZE 12 -#define ATAPI_BLOCK_SIZE 2048 #include "atapi-types.h" diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c index 43858a4..3605050 100644 --- a/palacios/src/devices/ide.c +++ b/palacios/src/devices/ide.c @@ -216,6 +216,10 @@ struct ide_internal { + + +/* Utility functions */ + static inline uint16_t be_to_le_16(const uint16_t val) { uint8_t * buf = (uint8_t *)&val; return (buf[0] << 8) | (buf[1]) ; @@ -265,6 +269,7 @@ static inline int is_lba_enabled(struct ide_channel * channel) { } +/* Drive Commands */ static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) { if (channel->ctrl_reg.irq_disable == 0) { PrintDebug("Raising IDE Interrupt %d\n", channel->irq); @@ -326,11 +331,89 @@ static void ide_abort_command(struct vm_device * dev, struct ide_channel * chann } -// Include the ATAPI interface handlers + +static void ide_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"; + const char* firmware = "ALPHA1 "; + + drive->transfer_length = 512; + drive->transfer_index = 0; + + + memset(drive_id->buf, 0, sizeof(drive_id->buf)); + + drive_id->fixed_drive = 1; + drive_id->removable_media = 0; + + // Black magic... + drive_id->disk_speed1 = 1; + drive_id->disk_speed3 = 1; + + 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; + + + // These buffers do not contain a terminating "\0" + memcpy(drive_id->serial_num, serial_number, strlen(serial_number)); + memcpy(drive_id->firmware_rev, firmware, strlen(firmware)); + memcpy(drive_id->model_num, drive->model, 40); + + // 32 bits access + drive_id->dword_io = 1; + + // enable DMA access + drive_id->dma_enable = 1; + + // enable LBA access + drive_id->lba_enable = 1; + + // Drive Capacity + drive_id->lba_capacity = drive->hd_ops->get_capacity(drive->private_data); + + 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] = 0x0000; // variable (DMA stuff) + + // drive_id->buf[64] = 0x0001; // PIO + drive_id->buf[65] = 0x00b4; + drive_id->buf[66] = 0x00b4; + drive_id->buf[67] = 0x012c; + drive_id->buf[68] = 0x00b4; + + drive_id->buf[71] = 30; // faked + drive_id->buf[72] = 30; // faked + + // 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->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported; +} + + + + + + + + +/* ATAPI functions */ #include "atapi.h" +/* IO Operations */ static int dma_read(struct vm_device * dev, struct ide_channel * channel) { struct ide_drive * drive = get_selected_drive(channel); struct ide_dma_prd prd_entry; @@ -593,8 +676,12 @@ static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_de // JRL: Should we abort here? ide_abort_command(dev, channel); } else { - PrintError("IDE Disks currently not implemented\n"); - return -1; + ide_identify_device(drive); + + channel->error_reg.val = 0; + channel->status.val = 0x58; + + ide_raise_irq(dev, channel); } break; @@ -1234,3 +1321,6 @@ int v3_ide_register_harddisk(struct vm_device * ide_dev, return 0; } + + + diff --git a/palacios/src/devices/ram_hd.c b/palacios/src/devices/ram_hd.c new file mode 100644 index 0000000..86554d6 --- /dev/null +++ b/palacios/src/devices/ram_hd.c @@ -0,0 +1,108 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include + + +struct hd_state { + addr_t disk_image; + uint32_t capacity; // in bytes + + struct vm_device * ide; + + uint_t bus; + uint_t drive; +}; + + +// HDs always read 2048 byte blocks... ? +static int hd_read(uint8_t * buf, int count, int lba, void * private_data) { + struct vm_device * hd_dev = (struct vm_device *)private_data; + struct hd_state * hd = (struct hd_state *)(hd_dev->private_data); + int offset = lba * IDE_SECTOR_SIZE; + int length = ((offset + count) > hd->capacity) ? (hd->capacity - offset) : count; + + PrintDebug("Reading RAM HD at (LBA=%d) offset %d (length=%d)\n", lba, offset, length); + + memcpy(buf, (uint8_t *)(hd->disk_image + offset), length); + + // Pad out the rest of the buffer with 0's + // memset(buf + length, 0, IDE_SECTOR_SIZE - length); + + return 0; +} + + +static uint32_t hd_get_capacity(void * private_data) { + struct vm_device * hd_dev = (struct vm_device *)private_data; + struct hd_state * hd = (struct hd_state *)(hd_dev->private_data); + PrintDebug("Querying RAM HD capacity (bytes=%d) (ret = %d)\n", + hd->capacity, (hd->capacity + IDE_SECTOR_SIZE - 1) / IDE_SECTOR_SIZE); + return (hd->capacity + IDE_SECTOR_SIZE - 1) / IDE_SECTOR_SIZE; +} + +static struct v3_ide_hd_ops hd_ops = { + .read = hd_read, + .get_capacity = hd_get_capacity, +}; + + +static int hd_init(struct vm_device * dev) { + struct hd_state * hd = (struct hd_state *)(dev->private_data); + + if (v3_ide_register_harddisk(hd->ide, hd->bus, hd->drive, "V3-RAM-HD", &hd_ops, dev) == -1) { + return -1; + } + + return 0; +} + + +static int hd_deinit(struct vm_device * dev) { + return 0; +} + +static struct vm_device_ops dev_ops = { + .init = hd_init, + .deinit = hd_deinit, + .reset = NULL, + .start = NULL, + .stop = NULL, +}; + +struct vm_device * v3_create_ram_hd(struct vm_device * ide, + uint_t bus, uint_t drive, + addr_t ramdisk, uint32_t size) { + struct hd_state * hd = (struct hd_state *)V3_Malloc(sizeof(struct hd_state)); + + PrintDebug("Registering Ram HDD at %p (size=%d)\n", (void *)ramdisk, size); + + hd->disk_image = ramdisk; + hd->capacity = size; + + hd->ide = ide; + hd->bus = bus; + hd->drive = drive; + + struct vm_device * hd_dev = v3_create_device("RAM-HD", &dev_ops, hd); + + return hd_dev; +} diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index be73f33..75e7834 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -280,7 +281,8 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) { struct vm_device * ide = NULL; - struct vm_device * ram_cd = NULL; + // struct vm_device * ram_cd = NULL; + struct vm_device * ram_hd = NULL; struct vm_device * pci = v3_create_pci(); struct vm_device * nvram = v3_create_nvram(); //struct vm_device * timer = v3_create_timer(); @@ -303,7 +305,10 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ if (use_ramdisk) { PrintDebug("Creating Ramdisk\n"); - ram_cd = v3_create_ram_cd(ide, 0, 0, + // ram_cd = v3_create_ram_cd(ide, 0, 0, + // (addr_t)(config_ptr->ramdisk), + // config_ptr->ramdisk_size); + ram_hd = v3_create_ram_hd(ide, 0, 0, (addr_t)(config_ptr->ramdisk), config_ptr->ramdisk_size); } @@ -333,7 +338,8 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ v3_attach_device(info, ide); if (use_ramdisk) { - v3_attach_device(info, ram_cd); + // v3_attach_device(info, ram_cd); + v3_attach_device(info, ram_hd); } if (use_generic) {