X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fnvram.c;h=10574e4e7d45129679660648529d3e08f72fa22e;hb=f44ca084bc46b20de6414920ab3a6fe53688095f;hp=da76b67b5be838ff93677eb9f9b89ecc3b6c41f2;hpb=101529b6eae500272347287df43ec51aa003d0aa;p=palacios-OLD.git diff --git a/palacios/src/devices/nvram.c b/palacios/src/devices/nvram.c index da76b67..10574e4 100644 --- a/palacios/src/devices/nvram.c +++ b/palacios/src/devices/nvram.c @@ -1,5 +1,22 @@ -/* (c) 2008, Peter Dinda */ -/* (c) 2008, The V3VEE Project */ +/* + * 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, Peter Dinda + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Peter Dinda + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + #include #include @@ -62,7 +79,6 @@ typedef enum {NVRAM_READY, NVRAM_REG_POSTED} nvram_state_t; #define NVRAM_REG_AMI_BIG_MEMORY_HIGH 0x35 #define NVRAM_REG_AMI_BIG_MEMORY_LOW 0x34 - #define NVRAM_REG_CSUM_HIGH 0x2e #define NVRAM_REG_CSUM_LOW 0x2f #define NVRAM_REG_IBM_CENTURY_BYTE 0x32 @@ -115,21 +131,14 @@ struct rtc_statd { -struct vm_device * thedev = NULL; - -static struct vm_device * demultiplex_timer_interrupt(uint_t period_us) -{ - // hack - return thedev; -} - struct bcd_num { uchar_t bot : 4; uchar_t top : 4; -} ; +}; -static uchar_t add_to(uchar_t * left, uchar_t * right, uchar_t bcd) -{ + + +static uchar_t add_to(uchar_t * left, uchar_t * right, uchar_t bcd) { uchar_t temp; if (bcd) { @@ -156,12 +165,10 @@ static uchar_t add_to(uchar_t * left, uchar_t * right, uchar_t bcd) return 0; } } - } -static uchar_t days_in_month(struct vm_device *dev, uchar_t month, uchar_t bcd) -{ +static uchar_t days_in_month(struct vm_device * dev, uchar_t month, uchar_t bcd) { // This completely ignores Julian / Gregorian stuff right now if (bcd) { @@ -219,8 +226,7 @@ static uchar_t days_in_month(struct vm_device *dev, uchar_t month, uchar_t bcd) } -static void update_time(struct vm_device *dev, uint_t period_us) -{ +static void update_time(struct vm_device * dev, uint_t period_us) { struct nvram_internal * data = (struct nvram_internal *) (dev->private_data); struct rtc_stata * stata = (struct rtc_stata *) &((data->mem_state[NVRAM_REG_STAT_A])); struct rtc_statb * statb = (struct rtc_statb *) &((data->mem_state[NVRAM_REG_STAT_B])); @@ -402,28 +408,73 @@ static void update_time(struct vm_device *dev, uint_t period_us) // Interrupt associated VM, if needed if (statc->irq) { PrintDebug("nvram: injecting interrupt\n"); - dev->vm->vm_ops.raise_irq(dev->vm, NVRAM_RTC_IRQ); + v3_raise_irq(dev->vm, NVRAM_RTC_IRQ); } } +static int handle_timer_event(struct guest_info * info, + struct v3_timer_event * evt, + void * priv_data) { - -void deliver_timer_interrupt_to_vmm(uint_t period_us) -{ - struct vm_device * dev = demultiplex_timer_interrupt(period_us); + struct vm_device * dev = (struct vm_device *)priv_data; if (dev) { - update_time(dev, period_us); + update_time(dev, evt->period_us); } + return 0; } -static int set_nvram_defaults(struct vm_device * dev) -{ - struct nvram_internal * nvram_state = (struct nvram_internal *)dev->private_data; +static void set_memory_size(struct nvram_internal * nvram, addr_t bytes) { + // 1. Conventional Mem: 0-640k in K + // 2. Extended Mem: 0-16MB in K + // 3. Big Mem: 0-4G in 64K + + if (bytes > 640 * 1024) { + nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02; + nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80; + } else { + uint16_t memk = bytes * 1024; + nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = (memk >> 8) & 0x00ff; + nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = memk & 0x00ff; + + return; + } + + if (bytes > (16 * 1024 * 1024)) { + // Set extended memory to 15 MB + nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00; + } else { + uint16_t memk = bytes * 1024; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = (memk >> 8) & 0x00ff; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = memk & 0x00ff; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= (memk >> 8) & 0x00ff; + nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= memk & 0x00ff; + + return; + } + + { + // Set the extended memory beyond 16 MB in 64k chunks + uint16_t mem_chunks = (bytes - (1024 * 1024 * 16)) / (1024 * 64); + nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = (mem_chunks >> 8) & 0x00ff; + nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = mem_chunks & 0x00ff; + } + + return; +} + +static int init_nvram_state(struct vm_device * dev) { + struct guest_info * info = dev->vm; + struct nvram_internal * nvram_state = (struct nvram_internal *)dev->private_data; + + memset(nvram_state->mem_state, 0, NVRAM_REG_MAX); // // 2 1.44 MB floppy drives @@ -448,30 +499,13 @@ static int set_nvram_defaults(struct vm_device * dev) // For new boot sequence style, do cd, hd, floppy nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x23; nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x10; - - + + // Set equipment byte to note 2 floppies, vga display, keyboard,math,floppy nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0x4f; - //nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf; - - // Set conventional memory to 640K - nvram_state->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02; - nvram_state->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80; - - // Set extended memory to 15 MB - nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C; - nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00; - nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C; - nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00; - - // Set the extended memory beyond 16 MB to 128-16 MB - nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = 0x7; - nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = 0x00; - - //nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH]= 0x00; - //nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW]= 0x00; - + // nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf; + // This is the harddisk type.... Set accordingly... nvram_state->mem_state[NVRAM_IBM_HD_DATA] = 0x20; @@ -507,21 +541,19 @@ static int set_nvram_defaults(struct vm_device * dev) nvram_state->us = 0; nvram_state->pus = 0; - return 0; + set_memory_size(nvram_state, info->mem_size); + + nvram_state->dev_state = NVRAM_READY; + nvram_state->thereg = 0; + return 0; } -int nvram_reset_device(struct vm_device * dev) -{ - struct nvram_internal * data = (struct nvram_internal *) dev->private_data; - - PrintDebug("nvram: reset device\n"); - - data->dev_state = NVRAM_READY; - data->thereg = 0; - + +static int nvram_reset_device(struct vm_device * dev) { + return 0; } @@ -529,15 +561,13 @@ int nvram_reset_device(struct vm_device * dev) -int nvram_start_device(struct vm_device *dev) -{ +static int nvram_start_device(struct vm_device * dev) { PrintDebug("nvram: start device\n"); return 0; } -int nvram_stop_device(struct vm_device *dev) -{ +static int nvram_stop_device(struct vm_device * dev) { PrintDebug("nvram: stop device\n"); return 0; } @@ -545,11 +575,10 @@ int nvram_stop_device(struct vm_device *dev) -int nvram_write_reg_port(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) -{ +static int nvram_write_reg_port(ushort_t port, + void * src, + uint_t length, + struct vm_device * dev) { struct nvram_internal * data = (struct nvram_internal *)dev->private_data; memcpy(&(data->thereg), src, 1); @@ -559,14 +588,11 @@ int nvram_write_reg_port(ushort_t port, return 1; } -int nvram_read_data_port(ushort_t port, - void * dst, - uint_t length, - struct vm_device * dev) -{ - struct nvram_internal * data = (struct nvram_internal *) dev->private_data; - - +static int nvram_read_data_port(ushort_t port, + void * dst, + uint_t length, + struct vm_device * dev) { + struct nvram_internal * data = (struct nvram_internal *)dev->private_data; memcpy(dst, &(data->mem_state[data->thereg]), 1); @@ -581,11 +607,10 @@ int nvram_read_data_port(ushort_t port, return 1; } -int nvram_write_data_port(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) -{ +static int nvram_write_data_port(ushort_t port, + void * src, + uint_t length, + struct vm_device * dev) { struct nvram_internal * data = (struct nvram_internal *)dev->private_data; memcpy(&(data->mem_state[data->thereg]), src, 1); @@ -597,32 +622,23 @@ int nvram_write_data_port(ushort_t port, -int nvram_init_device(struct vm_device * dev) { - - struct nvram_internal * data = (struct nvram_internal *) dev->private_data; - +static int nvram_init_device(struct vm_device * dev) { PrintDebug("nvram: init_device\n"); - memset(data->mem_state, 0, NVRAM_REG_MAX); - - // Would read state here - set_nvram_defaults(dev); - - nvram_reset_device(dev); + init_nvram_state(dev); // hook ports - dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port); - dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port); + v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port); + v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port); + v3_hook_host_event(dev->vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev); + return 0; } -int nvram_deinit_device(struct vm_device *dev) -{ - - - dev_unhook_io(dev, NVRAM_REG_PORT); - dev_unhook_io(dev, NVRAM_DATA_PORT); +static int nvram_deinit_device(struct vm_device * dev) { + v3_dev_unhook_io(dev, NVRAM_REG_PORT); + v3_dev_unhook_io(dev, NVRAM_DATA_PORT); nvram_reset_device(dev); return 0; @@ -643,18 +659,14 @@ static struct vm_device_ops dev_ops = { -struct vm_device * create_nvram() { - struct nvram_internal * nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal) + 1000); - - PrintDebug("nvram: internal at %x\n",nvram_state); +struct vm_device * v3_create_nvram() { + struct nvram_internal * nvram_state = NULL; - struct vm_device * device = create_device("NVRAM", &dev_ops, nvram_state); + nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal) + 1000); - if (thedev != NULL) { - PrintDebug("nvram: warning! overwriting thedev\n"); - } + PrintDebug("nvram: internal at %p\n", (void *)nvram_state); - thedev = device; + struct vm_device * device = v3_create_device("NVRAM", &dev_ops, nvram_state); return device; }