devices/para_net.o \
devices/ide.o \
devices/ram_cd.o \
+ devices/ram_hd.o \
# devices/cdrom.o \
# devices/ramdisk.o \
#include <palacios/vm_dev.h>
+#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 {
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);
};
--- /dev/null
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * 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 <palacios/vm_dev.h>
+
+
+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
*/
#define ATAPI_PACKET_SIZE 12
-#define ATAPI_BLOCK_SIZE 2048
#include "atapi-types.h"
+
+
+/* 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]) ;
}
+/* 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);
}
-// 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;
// 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;
return 0;
}
+
+
+
--- /dev/null
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <devices/ram_hd.h>
+#include <devices/ide.h>
+
+
+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;
+}
#include <devices/generic.h>
#include <devices/ide.h>
#include <devices/ram_cd.h>
+#include <devices/ram_hd.h>
#include <devices/bochs_debug.h>
#include <devices/os_debug.h>
#include <devices/apic.h>
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();
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);
}
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) {