X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Framdisk.c;h=9a2e7162ddbca173c948d6bcb8149add195b7f48;hb=123a1ba27ea09c8fa77a1b36ce625b43d7c48b14;hp=2d862fe06106bebda233f9d253cf378bae138d28;hpb=6593ee3c311ec87304c7bed52a9e6034338679fb;p=palacios.git diff --git a/palacios/src/devices/ramdisk.c b/palacios/src/devices/ramdisk.c index 2d862fe..9a2e716 100644 --- a/palacios/src/devices/ramdisk.c +++ b/palacios/src/devices/ramdisk.c @@ -1,2639 +1,137 @@ /* + * 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. * - * Copyright (C) 2002 MandrakeSoft S.A. - * - * MandrakeSoft S.A. - * 43, rue d'Aboukir - * 75002 Paris - France - * http://www.linux-mandrake.com/ - * http://www.mandrakesoft.com/ - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Major modifications made for the V3VEE project - * * 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, Zheng Cui - * Copyright (c) 2008, Jack Lange + * + * Copyright (c) 2008, Jack Lange * Copyright (c) 2008, The V3VEE Project - * All rights reserved for original changes - * + * 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 -#include +#include -#ifndef DEBUG_RAMDISK +#ifndef CONFIG_DEBUG_RAMDISK #undef PrintDebug -#define PrintDebug(_f, _a...) +#define PrintDebug(fmt, args...) #endif - - -/* - * Data type definitions - * - */ -#define INDEX_PULSE_CYCLE 10 - - - - -#define INTR_REASON_BIT_ERR 0x01 -#define UNABLE_FIND_TAT_CHANNEL_ERR 0x02 -#define DRQ_ERR 0x03 -#define READ_BUF_GT_512 0x04 - - - -#define PRI_DATA_PORT 0x1f0 -#define PRI_FEATURES_PORT 0x1f1 -#define PRI_SECT_CNT_PORT 0x1f2 -#define PRI_SECT_ADDR1_PORT 0x1f3 -#define PRI_SECT_ADDR2_PORT 0x1f4 -#define PRI_SECT_ADDR3_PORT 0x1f5 -#define PRI_DRV_SEL_PORT 0x1f6 -#define PRI_CMD_PORT 0x1f7 -#define PRI_CTRL_PORT 0x3f6 -#define PRI_ADDR_REG_PORT 0x3f7 - -#define SEC_DATA_PORT 0x170 -#define SEC_FEATURES_PORT 0x171 -#define SEC_SECT_CNT_PORT 0x172 -#define SEC_SECT_ADDR1_PORT 0x173 -#define SEC_SECT_ADDR2_PORT 0x174 -#define SEC_SECT_ADDR3_PORT 0x175 -#define SEC_DRV_SEL_PORT 0x176 -#define SEC_CMD_PORT 0x177 -#define SEC_CTRL_PORT 0x376 -#define SEC_ADDR_REG_PORT 0x377 - - - - - -#define PACKET_SIZE 12 - - -/* - * Debug facilities - */ - -#define ATA_DETECT 0xf0 //0X3E8 -#define ATA_RESET 0xf1 //0X3E9 -#define ATA_CMD_DATA_IN 0xf2 //0X3EA -#define ATA_CMD_DATA_OUT 0xf3 //0X3EB -#define ATA_CMD_PACKET 0xf4 //0X3EC -#define ATAPI_GET_SENSE 0xf5 //0X3ED -#define ATAPI_IS_READY 0xf6 //0X3EE -#define ATAPI_IS_CDROM 0xf7 //0X3EF - -#define CDEMU_INIT 0xf8 //0X2E8 -#define CDEMU_ISACTIVE 0xf9 //0X2E9 -#define CDEMU_EMULATED_DRIVE 0xfa //0X2EA -#define CDROM_BOOT 0xfb //0X2EB - - -#define HARD_DRIVE_POST 0xfc //0X2EC - - -#define ATA_DEVICE_NO 0xfd //0X2ED -#define ATA_DEVICE_TYPE 0xfe //0X2ED - -#define INT13_HARDDISK 0xff //0x2ef -#define INT13_CDROM 0xe0 //0x2f8 -#define INT13_CDEMU 0xe1 //0x2f9 -#define INT13_ELTORITO 0xe2 //0x2fa -#define INT13_DISKETTE_FUNCTION 0xe3 //0x2fb - - - - -static const char cdrom_str[] = "CD-ROM"; -static const char harddisk_str[] = "HARDDISK"; -static const char none_str[] = "NONE"; - - -static inline const char * device_type_to_str(device_type_t type) { - switch (type) { - case IDE_DISK: - return harddisk_str; - case IDE_CDROM: - return cdrom_str; - case IDE_NONE: - return none_str; - default: - return NULL; - } -} - - -static inline void write_features(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.features = value; - channel->drives[1].controller.features = value; -} - - -static inline void write_sector_count(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.sector_count = value; - channel->drives[1].controller.sector_count = value; -} - -static inline void write_sector_number(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.sector_no = value; - channel->drives[1].controller.sector_no = value; -} - - -static inline void write_cylinder_low(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.cylinder_no &= 0xff00; - channel->drives[0].controller.cylinder_no |= value; - channel->drives[1].controller.cylinder_no &= 0xff00; - channel->drives[1].controller.cylinder_no |= value; -} - -static inline void write_cylinder_high(struct channel_t * channel, uchar_t value) { - ushort_t val2 = value; - val2 = val2 << 8; - channel->drives[0].controller.cylinder_no &= 0x00ff; - channel->drives[0].controller.cylinder_no |= (val2 & 0xff00); - - channel->drives[1].controller.cylinder_no &= 0x00ff; - channel->drives[1].controller.cylinder_no |= (val2 & 0xff00); -} - -static inline void write_head_no(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.head_no = value; - channel->drives[1].controller.head_no = value; -} - -static inline void write_lba_mode(struct channel_t * channel, uchar_t value) { - channel->drives[0].controller.lba_mode = value; - channel->drives[1].controller.lba_mode = value; -} - - -static inline uint_t get_channel_no(struct ramdisk_t * ramdisk, struct channel_t * channel) { - return (((uchar_t *)channel - (uchar_t *)(ramdisk->channels)) / sizeof(struct channel_t)); -} - -static inline uint_t get_drive_no(struct channel_t * channel, struct drive_t * drive) { - return (((uchar_t *)drive - (uchar_t*)(channel->drives)) / sizeof(struct drive_t)); -} - -static inline struct drive_t * get_selected_drive(struct channel_t * channel) { - return &(channel->drives[channel->drive_select]); -} +struct disk_state { + uint8_t * disk_image; + uint32_t capacity; // in bytes +}; -static inline int is_primary_port(struct ramdisk_t * ramdisk, ushort_t port) { - switch(port) - { - case PRI_DATA_PORT: - case PRI_FEATURES_PORT: - case PRI_SECT_CNT_PORT: - case PRI_SECT_ADDR1_PORT: - case PRI_SECT_ADDR2_PORT: - case PRI_SECT_ADDR3_PORT: - case PRI_DRV_SEL_PORT: - case PRI_CMD_PORT: - case PRI_CTRL_PORT: - return 1; - default: - return 0; - } -} +static int read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) { + struct disk_state * disk = (struct disk_state *)private_data; + PrintDebug("Reading %d bytes from %p to %p\n", (uint32_t)num_bytes, (uint8_t *)(disk->disk_image + lba), buf); -static inline int is_secondary_port(struct ramdisk_t * ramdisk, ushort_t port) { - switch(port) - { - case SEC_DATA_PORT: - case SEC_FEATURES_PORT: - case SEC_SECT_CNT_PORT: - case SEC_SECT_ADDR1_PORT: - case SEC_SECT_ADDR2_PORT: - case SEC_SECT_ADDR3_PORT: - case SEC_DRV_SEL_PORT: - case SEC_CMD_PORT: - case SEC_CTRL_PORT: - return 1; - default: - return 0; - } -} + memcpy(buf, (uint8_t *)(disk->disk_image + lba), num_bytes); -static inline int num_drives_on_channel(struct channel_t * channel) { - if ((channel->drives[0].device_type == IDE_NONE) && - (channel->drives[1].device_type == IDE_NONE)) { return 0; - } else if ((channel->drives[0].device_type != IDE_NONE) && - (channel->drives[1].device_type != IDE_NONE)) { - return 2; - } else { - return 1; - } -} - - - -static inline uchar_t extract_bits(uchar_t * buf, uint_t buf_offset, uint_t bit_offset, uint_t num_bits) { - uchar_t val = buf[buf_offset]; - val = val >> bit_offset; - val &= ((1 << num_bits) -1); - return val; } -static inline uchar_t get_packet_field(struct channel_t * channel, uint_t packet_offset, uint_t bit_offset, uint_t num_bits) { - struct drive_t * drive = get_selected_drive(channel); - return extract_bits(drive->controller.buffer, packet_offset, bit_offset, num_bits); -} - - -static inline uchar_t get_packet_byte(struct channel_t * channel, uint_t offset) { - struct drive_t * drive = get_selected_drive(channel); - return drive->controller.buffer[offset]; -} - -static inline uint16_t get_packet_word(struct channel_t * channel, uint_t offset) { - struct drive_t * drive = get_selected_drive(channel); - uint16_t val = drive->controller.buffer[offset]; - val = val << 8; - val |= drive->controller.buffer[offset + 1]; - return val; -} - - -static inline uint16_t rd_read_16bit(const uint8_t* buf) { - return (buf[0] << 8) | buf[1]; -} - - - -static inline uint32_t rd_read_32bit(const uint8_t* buf) { - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - -//////////////////////////////////////////////////////////////////////////// - - -/* - * ATAPI routines - */ - - -static void rd_init_mode_sense_single(struct vm_device * dev, struct channel_t * channel, const void * src, int size); - -static void rd_command_aborted(struct vm_device * dev, struct channel_t * channel, unsigned value); - - - - -static int handle_atapi_packet_command(struct vm_device * dev, - struct channel_t * channel, - ushort_t val); - -static int rd_init_send_atapi_command(struct vm_device * dev, - struct channel_t * channel, - Bit8u command, int req_length, - int alloc_length, bool lazy); - -static void rd_ready_to_send_atapi(struct vm_device * dev, - struct channel_t * channel); - -static void rd_atapi_cmd_error(struct vm_device * dev, - struct channel_t * channel, - sense_t sense_key, asc_t asc); - -static void rd_atapi_cmd_nop(struct vm_device * dev, struct channel_t * channel); -static void rd_identify_ATAPI_drive(struct vm_device * dev, struct channel_t * channel); - - - -/* - * Interrupt handling - */ -static void rd_raise_interrupt(struct vm_device * dev, struct channel_t * channel); -static void rd_lower_irq(struct vm_device *dev, Bit32u irq); - - - -/* - * Helper routines - */ - - - -#ifdef DEBUG_RAMDISK -static void rd_print_state(struct ramdisk_t *ramdisk); -static int check_bit_fields(struct controller_t * controller); -#endif -//////////////////////////////////////////////////////////////////// - - - - - -int v3_ramdisk_register_cdrom(struct vm_device * dev, uint_t busID, uint_t driveID, struct cdrom_ops* cd, void * private_data) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = &(ramdisk->channels[busID]); - struct drive_t * drive = &(channel->drives[driveID]); - struct controller_t * controller = &(drive->controller); - +static int write(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) { + struct disk_state * disk = (struct disk_state *)private_data; - - if (drive->device_type != IDE_NONE) { - PrintError("Device already registered at this location\n"); - return -1; - } + PrintDebug("Writing %d bytes from %p to %p\n", (uint32_t)num_bytes, buf, (uint8_t *)(disk->disk_image + lba)); + memcpy((uint8_t *)(disk->disk_image + lba), buf, num_bytes); - channel->irq = 15; - - // Make model string - strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40); - - while (strlen((char *)(drive->model_no)) < 40) { - strcat ((char*)(drive->model_no), " "); - } - - PrintDebug("CDROM on target %d/%d\n", busID, driveID); - - drive->device_type = IDE_CDROM; - drive->cdrom.locked = 0; - drive->sense.sense_key = SENSE_NONE; - drive->sense.asc = 0; - drive->sense.ascq = 0; - - drive->private_data = private_data; - -#ifdef DEBUG_RAMDISK - if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) { - PrintDebug("interrupt reason: bit field error\n"); - return INTR_REASON_BIT_ERR; - } -#endif - - controller->sector_count = 0; - - drive->cdrom.cd = cd; - - PrintDebug("\t\tCD on ata%d-%d: '%s'\n", - busID, - driveID, ""); - - if(drive->cdrom.cd->insert_cdrom(drive->private_data)) { - PrintDebug("\t\tMedia present in CD-ROM drive\n"); - drive->cdrom.ready = 1; - drive->cdrom.capacity = drive->cdrom.cd->capacity(drive->private_data); - PrintDebug("\t\tCDROM capacity is %d\n", drive->cdrom.capacity); - } else { - PrintDebug("\t\tCould not locate CD-ROM, continuing with media not present\n"); - drive->cdrom.ready = 0; - } - - return 0; -} - - -static Bit32u rd_init_hardware(struct ramdisk_t *ramdisk) { - uint_t channel_num; - uint_t device; - struct channel_t *channels = (struct channel_t *)(&(ramdisk->channels)); - - PrintDebug("[rd_init_harddrive]\n"); - - for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++) { - memset((char *)(channels + channel_num), 0, sizeof(struct channel_t)); - } - - for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++){ - struct channel_t * channel = &(channels[channel_num]); - - channel->ioaddr1 = 0x0; - channel->ioaddr2 = 0x0; - channel->irq = 0; - - for (device = 0; device < 2; device++){ - struct drive_t * drive = &(channel->drives[device]); - struct controller_t * controller = &(drive->controller); - - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.write_fault = 0; - controller->status.seek_complete = 1; - controller->status.drq = 0; - controller->status.corrected_data = 0; - controller->status.index_pulse = 0; - controller->status.index_pulse_count = 0; - controller->status.err = 0; - - controller->error_register = 0x01; // diagnostic code: no error - controller->head_no = 0; - controller->sector_count = 1; - controller->sector_no = 1; - controller->cylinder_no = 0; - controller->current_command = 0x00; - controller->buffer_index = 0; - - controller->control.reset = 0; - controller->control.disable_irq = 0; - controller->reset_in_progress = 0; - - controller->sectors_per_block = 0x80; - controller->lba_mode = 0; - - - controller->features = 0; - - // If not present - drive->device_type = IDE_NONE; - - // Make model string - strncpy((char*)(drive->model_no), "", 40); - while(strlen((char *)(drive->model_no)) < 40) { - strcat ((char*)(drive->model_no), " "); - } - - }//for device - }//for channel - -#ifdef DEBUG_RAMDISK - rd_print_state(ramdisk); -#endif - return 0; -} - - -/* - static void rd_reset_harddrive(struct ramdisk_t *ramdisk, unsigned type) { - return; - } - -*/ -static void rd_close_harddrive(struct ramdisk_t *ramdisk) { - return; -} - - -//////////////////////////////////////////////////////////////////// - - - -static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - - - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - - - PrintDebug("[read_data_handler] IO Read at 0x%x, on drive %d/%d (current_cmd = 0x%02x)\n", - port, - get_channel_no(ramdisk, channel), - get_drive_no(channel, drive), - controller->current_command); - - switch (controller->current_command) { - case 0xec: // IDENTIFY DEVICE - case 0xa1: - { - - - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.write_fault = 0; - controller->status.seek_complete = 1; - controller->status.corrected_data = 0; - controller->status.err = 0; - - /* - value32 = controller->buffer[index]; - index++; - - if (io_len >= 2) { - value32 |= (controller->buffer[index] << 8); - index++; - } - - if (io_len == 4) { - value32 |= (controller->buffer[index] << 16); - value32 |= (controller->buffer[index+1] << 24); - index += 2; - } - - controller->buffer_index = index; - */ - /* JRL */ - memcpy(dst, controller->buffer + controller->buffer_index, length); - controller->buffer_index += length; - - if (controller->buffer_index >= 512) { - controller->status.drq = 0; - } - - return length; - } - case 0xa0: //send packet cmd - { - uint_t index = controller->buffer_index; - - - PrintDebug("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n", - drive->atapi.command, - index, - drive->cdrom.remaining_blocks); - - // Load block if necessary - if (index >= 2048) { - - if (index > 2048) { - PrintError("\t\tindex > 2048 : 0x%x\n", index); - return -1; - } - - switch (drive->atapi.command) { - case 0x28: // read (10) - case 0xa8: // read (12) - { - - if (!(drive->cdrom.ready)) { - PrintError("\t\tRead with CDROM not ready\n"); - return -1; - } - - drive->cdrom.cd->read_block(drive->private_data, controller->buffer, - drive->cdrom.next_lba); - drive->cdrom.next_lba++; - drive->cdrom.remaining_blocks--; - - - if (!(drive->cdrom.remaining_blocks)) { - PrintDebug("\t\tLast READ block loaded {CDROM}\n"); - } else { - PrintDebug("\t\tREAD block loaded (%d remaining) {CDROM}\n", - drive->cdrom.remaining_blocks); - } - - // one block transfered, start at beginning - index = 0; - break; - } - default: // no need to load a new block - break; - } - } - - - /* - increment = 0; - value32 = controller->buffer[index + increment]; - increment++; - - if (io_len >= 2) { - value32 |= (controller->buffer[index + increment] << 8); - increment++; - } - - if (io_len == 4) { - value32 |= (controller->buffer[index + increment] << 16); - value32 |= (controller->buffer[index + increment + 1] << 24); - increment += 2; - } - - controller->buffer_index = index + increment; - controller->drq_index += increment; - - */ - /* JRL: CHECK THAT there is enough data in the buffer to copy.... */ - { - memcpy(dst, controller->buffer + index, length); - - controller->buffer_index = index + length; - controller->drq_index += length; - } - - /* *** */ - - if (controller->drq_index >= (unsigned)drive->atapi.drq_bytes) { - controller->status.drq = 0; - controller->drq_index = 0; - - drive->atapi.total_bytes_remaining -= drive->atapi.drq_bytes; - - if (drive->atapi.total_bytes_remaining > 0) { - // one or more blocks remaining (works only for single block commands) - - PrintDebug("\t\tPACKET drq bytes read\n"); - controller->interrupt_reason.i_o = 1; - controller->status.busy = 0; - controller->status.drq = 1; - controller->interrupt_reason.c_d = 0; - - // set new byte count if last block - if (drive->atapi.total_bytes_remaining < controller->byte_count) { - controller->byte_count = drive->atapi.total_bytes_remaining; - } - drive->atapi.drq_bytes = controller->byte_count; - - rd_raise_interrupt(dev, channel); - } else { - // all bytes read - PrintDebug("\t\tPACKET all bytes read\n"); - - controller->interrupt_reason.i_o = 1; - controller->interrupt_reason.c_d = 1; - controller->status.drive_ready = 1; - controller->interrupt_reason.rel = 0; - controller->status.busy = 0; - controller->status.drq = 0; - controller->status.err = 0; - - rd_raise_interrupt(dev, channel); - } - } - return length; - break; - } - - default: - PrintDebug("\t\tread need support more command: %02x\n", controller->current_command); - break; - } - - return -1; -} - - - - -static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - - PrintDebug("[write_data_handler] IO write at 0x%x, current_cmd = 0x%02x\n", - port, controller->current_command); - - switch (controller->current_command) { - case 0x30: // WRITE SECTORS - PrintError("\t\tneed to implement 0x30(write sector) to port 0x%x\n", port); - return -1; - - case 0xa0: // PACKET - - if (handle_atapi_packet_command(dev, channel, *(ushort_t *)src) == -1) { - return -1; - } - - return length; - - default: - PrintError("\t\tIO write(0x%x): current command is %02xh\n", - port, controller->current_command); - - return -1; - } -} - - - - - - - -static int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - - - if (length != 1) { - PrintError("Invalid Status port read length: %d (port=%d)\n", length, port); - return -1; - } - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - - PrintDebug("[read_status_handler] IO read at 0x%x, on drive %d/%d\n", - port, get_channel_no(ramdisk, channel), - channel->drive_select); - - - if (num_drives_on_channel(channel) == 0) { - // (mch) Just return zero for these registers - memset(dst, 0, length); - - } else { - uchar_t val = ( - (controller->status.busy << 7) | - (controller->status.drive_ready << 6) | - (controller->status.write_fault << 5) | - (controller->status.seek_complete << 4) | - (controller->status.drq << 3) | - (controller->status.corrected_data << 2) | - (controller->status.index_pulse << 1) | - (controller->status.err) ); - - memcpy(dst, &val, length); - - controller->status.index_pulse_count++; - controller->status.index_pulse = 0; - - if (controller->status.index_pulse_count >= INDEX_PULSE_CYCLE) { - controller->status.index_pulse = 1; - controller->status.index_pulse_count = 0; - } - } - - if ((port == SEC_CMD_PORT) || (port == PRI_CMD_PORT)) { - rd_lower_irq(dev, channel->irq); - } - - return length; - + return 0; } -static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - uchar_t value = *(uchar_t *)src; - - if (length != 1) { - PrintError("Invalid Command port write length: %d (port=%d)\n", length, port); - return -1; - } - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - +static uint64_t get_capacity(void * private_data) { + struct disk_state * disk = (struct disk_state *)private_data; - PrintDebug("[write_command_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n", - port, get_channel_no(ramdisk, channel), - channel->drive_select, - value); + PrintDebug("Querying RAMDISK capacity %d\n", + (uint32_t)(disk->capacity)); - switch (value) { - // ATAPI commands - case 0xa1: // IDENTIFY PACKET DEVICE - { - if (drive->device_type == IDE_CDROM) { - controller->current_command = value; - controller->error_register = 0; - - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.write_fault = 0; - controller->status.drq = 1; - controller->status.err = 0; - - controller->status.seek_complete = 1; - controller->status.corrected_data = 0; - - controller->buffer_index = 0; - rd_raise_interrupt(dev, channel); - rd_identify_ATAPI_drive(dev, channel); - } else { - rd_command_aborted(dev, channel, 0xa1); - } - break; - } - case 0xa0: // SEND PACKET (atapi) - { - if (drive->device_type == IDE_CDROM) { - // PACKET - - if (controller->features & (1 << 0)) { - PrintError("\t\tPACKET-DMA not supported"); - return -1; - } - - if (controller->features & (1 << 1)) { - PrintError("\t\tPACKET-overlapped not supported"); - return -1; - } - - // We're already ready! - controller->sector_count = 1; - controller->status.busy = 0; - controller->status.write_fault = 0; - - // serv bit?? - controller->status.drq = 1; - controller->status.err = 0; - - // NOTE: no interrupt here - controller->current_command = value; - controller->buffer_index = 0; - } else { - rd_command_aborted (dev, channel, 0xa0); - } - break; - } - default: - PrintError("\t\tneed translate command %2x\n", value); - //return -1; - /* JRL THIS NEEDS TO CHANGE */ - return length; - - } - return length; + return disk->capacity; } +static struct v3_dev_blk_ops blk_ops = { + .read = read, + .write = write, + .get_capacity = get_capacity, +}; -static int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * master_drive = NULL; - struct drive_t * slave_drive = NULL; - struct controller_t * controller = NULL; - uchar_t value = *(uchar_t *)src; - rd_bool prev_control_reset; - - if (length != 1) { - PrintError("Invalid Status port read length: %d (port=%d)\n", length, port); - return -1; - } - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - master_drive = &(channel->drives[0]); - slave_drive = &(channel->drives[1]); - - controller = &(get_selected_drive(channel)->controller); - - - PrintDebug("[write_control_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n", - port, get_channel_no(ramdisk, channel), - channel->drive_select, - value); - - // (mch) Even if device 1 was selected, a write to this register - // goes to device 0 (if device 1 is absent) - - prev_control_reset = controller->control.reset; - - master_drive->controller.control.reset = value & 0x04; - slave_drive->controller.control.reset = value & 0x04; - - // CGS: was: SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02; - master_drive->controller.control.disable_irq = value & 0x02; - slave_drive->controller.control.disable_irq = value & 0x02; - - PrintDebug("\t\tadpater control reg: reset controller = %d\n", - (unsigned) (controller->control.reset) ? 1 : 0); - PrintDebug("\t\tadpater control reg: disable_irq(X) = %d\n", - (unsigned) (controller->control.disable_irq) ? 1 : 0); - - if ((!prev_control_reset) && (controller->control.reset)) { - uint_t id = 0; - - // transition from 0 to 1 causes all drives to reset - PrintDebug("\t\thard drive: RESET\n"); - - // (mch) Set BSY, drive not ready - for (id = 0; id < 2; id++) { - struct controller_t * ctrl = NULL; - - if (id == 0) { - ctrl = &(master_drive->controller); - } else if (id == 1) { - ctrl = &(slave_drive->controller); - } - - ctrl->status.busy = 1; - ctrl->status.drive_ready = 0; - ctrl->reset_in_progress = 1; - - ctrl->status.write_fault = 0; - ctrl->status.seek_complete = 1; - ctrl->status.drq = 0; - ctrl->status.corrected_data = 0; - ctrl->status.err = 0; - - ctrl->error_register = 0x01; // diagnostic code: no error - - ctrl->current_command = 0x00; - ctrl->buffer_index = 0; - - ctrl->sectors_per_block = 0x80; - ctrl->lba_mode = 0; - - ctrl->control.disable_irq = 0; - } - - rd_lower_irq(dev, channel->irq); - - } else if ((controller->reset_in_progress) && - (!controller->control.reset)) { - uint_t id; - // Clear BSY and DRDY - PrintDebug("\t\tReset complete {%s}\n", device_type_to_str(get_selected_drive(channel)->device_type)); - - for (id = 0; id < 2; id++) { - struct controller_t * ctrl = NULL; - struct drive_t * drv = NULL; - if (id == 0) { - ctrl = &(master_drive->controller); - drv = master_drive; - } else if (id == 1) { - ctrl = &(slave_drive->controller); - drv = slave_drive; - } - ctrl->status.busy = 0; - ctrl->status.drive_ready = 1; - ctrl->reset_in_progress = 0; - - // Device signature - if (drv->device_type == IDE_DISK) { - PrintDebug("\t\tdrive %d/%d is harddrive\n", get_channel_no(ramdisk, channel), id); - ctrl->head_no = 0; - ctrl->sector_count = 1; - ctrl->sector_no = 1; - ctrl->cylinder_no = 0; - } else { - ctrl->head_no = 0; - ctrl->sector_count = 1; - ctrl->sector_no = 1; - ctrl->cylinder_no = 0xeb14; - } - } - } - PrintDebug("\t\ts[0].controller.control.disable_irq = %02x\n", - master_drive->controller.control.disable_irq); - PrintDebug("\t\ts[1].controller.control.disable_irq = %02x\n", - slave_drive->controller.control.disable_irq); - return length; +static int disk_free(struct vm_device * dev) { + return 0; } +static struct v3_device_ops dev_ops = { + .free = disk_free, + .reset = NULL, + .start = NULL, + .stop = NULL, +}; -static int read_general_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - - - if (length != 1) { - PrintError("Invalid Status port read length: %d (port=%d)\n", length, port); - return -1; - } - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - - - PrintDebug("[read_general_handler] IO read addr at %x, on drive %d/%d, curcmd = %02x\n", - port, get_channel_no(ramdisk, channel), - channel->drive_select, - controller->current_command); - - - switch (port) { - case PRI_FEATURES_PORT: - case SEC_FEATURES_PORT: // hard disk error register 0x1f1 - { - uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->error_register; - - controller->status.err = 0; - - *(uchar_t *)dst = val; - return length; - - break; - } - - case PRI_SECT_CNT_PORT: - case SEC_SECT_CNT_PORT: // hard disk sector count / interrupt reason 0x1f2 - { - uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_count; - - *(uchar_t *)dst = val; - return length; - - break; - } - case PRI_SECT_ADDR1_PORT: - case SEC_SECT_ADDR1_PORT: // sector number 0x1f3 - { - uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_no; - - *(uchar_t *)dst = val; - return length; - - break; - } - case PRI_SECT_ADDR2_PORT: - case SEC_SECT_ADDR2_PORT: // cylinder low 0x1f4 - { - // -- WARNING : On real hardware the controller registers are shared between drives. - // So we must respond even if the select device is not present. Some OS uses this fact - // to detect the disks.... minix2 for example - uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no & 0x00ff); - *(uchar_t *)dst = val; - return length; - break; - } +static int disk_init(struct guest_info * vm, v3_cfg_tree_t * cfg) { + struct disk_state * disk = NULL; + struct v3_cfg_file * file = NULL; + char * name = v3_cfg_val(cfg, "name"); + char * filename = v3_cfg_val(cfg, "file"); - case PRI_SECT_ADDR3_PORT: - case SEC_SECT_ADDR3_PORT: // cylinder high 0x1f5 - { - // -- WARNING : On real hardware the controller registers are shared between drives. - // So we must respond even if the select device is not present. Some OS uses this fact - // to detect the disks.... minix2 for example - uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no >> 8); + v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend"); - *(uchar_t *)dst = val; - return length; + disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state)); + memset(disk, 0, sizeof(struct disk_state)); - break; - } - case PRI_DRV_SEL_PORT: - case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6 - { - // b7 Extended data field for ECC - // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 - // Since 512 was always used, bit 6 was taken to mean LBA mode: - // b6 1=LBA mode, 0=CHS mode - // b5 1 - // b4: DRV - // b3..0 HD3..HD0 - uchar_t val = ((1 << 7) | - ((controller->lba_mode > 0) << 6) | - (1 << 5) | // 01b = 512 sector size - (channel->drive_select << 4) | - (controller->head_no << 0)); - - *(uchar_t *)dst = val; - return length; - break; - } - case PRI_ADDR_REG_PORT: - case SEC_ADDR_REG_PORT: // Hard Disk Address Register 0x3f7 - { - // Obsolete and unsupported register. Not driven by hard - // disk controller. Report all 1's. If floppy controller - // is handling this address, it will call this function - // set/clear D7 (the only bit it handles), then return - // the combined value - *(uchar_t *)dst = 0xff; - return length; + if (!filename) { + PrintError("Missing filename (%s) for %s\n", filename, name); + return -1; } - default: - PrintError("Invalid Port: %d\n", port); - return -1; - } -} - - - + file = v3_cfg_get_file(vm, filename); -static int write_general_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct channel_t * channel = NULL; - struct drive_t * drive = NULL; - struct controller_t * controller = NULL; - uchar_t value = *(uchar_t *)src; - - if (length != 1) { - PrintError("Invalid Status port read length: %d (port=%d)\n", length, port); - return -1; - } - - if (is_primary_port(ramdisk, port)) { - channel = &(ramdisk->channels[0]); - } else if (is_secondary_port(ramdisk, port)) { - channel = &(ramdisk->channels[1]); - } else { - PrintError("Invalid Port: %d\n", port); - return -1; - } - - drive = get_selected_drive(channel); - controller = &(drive->controller); - - - PrintDebug("[write_general_handler] IO write to port %x (val=0x%02x), channel = %d\n", - port, value, get_channel_no(ramdisk, channel)); - - switch (port) { - - case PRI_FEATURES_PORT: - case SEC_FEATURES_PORT: // hard disk write precompensation 0x1f1 - { - write_features(channel, value); - break; - } - case PRI_SECT_CNT_PORT: - case SEC_SECT_CNT_PORT: // hard disk sector count 0x1f2 - { - write_sector_count(channel, value); - break; - } - case PRI_SECT_ADDR1_PORT: - case SEC_SECT_ADDR1_PORT: // hard disk sector number 0x1f3 - { - write_sector_number(channel, value); - break; + if (!file) { + PrintError("Invalid ramdisk file: %s\n", filename); + return -1; } - case PRI_SECT_ADDR2_PORT: - case SEC_SECT_ADDR2_PORT: // hard disk cylinder low 0x1f4 - { - write_cylinder_low(channel, value); - break; - } - case PRI_SECT_ADDR3_PORT: - case SEC_SECT_ADDR3_PORT: // hard disk cylinder high 0x1f5 - { - write_cylinder_high(channel, value); - break; - } - case PRI_DRV_SEL_PORT: - case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6 - { - // b7 Extended data field for ECC - // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 - // Since 512 was always used, bit 6 was taken to mean LBA mode: - // b6 1=LBA mode, 0=CHS mode - // b5 1 - // b4: DRV - // b3..0 HD3..HD0 - - // 1x1xxxxx - - PrintDebug("\tDrive Select value=%x\n", value); - - if ((value & 0xa0) != 0xa0) { - PrintDebug("\t\tIO write 0x%x (%02x): not 1x1xxxxxb\n", port, (unsigned) value); - } - - write_head_no(channel, value & 0xf); - if ((controller->lba_mode == 0) && (((value >> 6) & 1) == 1)) { - PrintDebug("\t\tenabling LBA mode\n"); - } - - write_lba_mode(channel, (value >> 6) & 1); - - - if (drive->cdrom.cd) { - PrintDebug("\t\tSetting LBA on CDROM: %d\n", (value >> 6) & 1); - drive->cdrom.cd->set_LBA(drive->private_data, (value >> 6) & 1); - } - + disk->disk_image = file->data; + disk->capacity = file->size; + PrintDebug("Registering RAMDISK at %p (size=%d)\n", + (void *)file->data, (uint32_t)file->size); - channel->drive_select = (value >> 4) & 0x01; - drive = get_selected_drive(channel); + struct vm_device * dev = v3_allocate_device(name, &dev_ops, disk); - if (drive->device_type == IDE_NONE) { - PrintDebug("\t\tError: device set to %d which does not exist! channel = 0x%x\n", - channel->drive_select, get_channel_no(ramdisk, channel)); - - controller->error_register = 0x04; // aborted - controller->status.err = 1; - } - - break; + if (v3_attach_device(vm, dev) == -1) { + PrintError("Could not attach device %s\n", name); + return -1; } - default: - PrintError("\t\thard drive: io write to unhandled port 0x%x (value = %c)\n", port, value); - //return -1; - } - - return length; -} - - - - - -static void rd_raise_interrupt(struct vm_device * dev, struct channel_t * channel) { - Bit32u irq; - // struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct drive_t * drive = get_selected_drive(channel); - struct controller_t * controller = &(drive->controller); - - PrintDebug("[raise_interrupt] disable_irq = %02x\n", controller->control.disable_irq); - - if (!(controller->control.disable_irq)) { - irq = channel->irq; - - PrintDebug("\t\tRaising interrupt %d {%s}\n\n", irq, device_type_to_str(drive->device_type)); - - dev->vm->vm_ops.raise_irq(dev->vm, irq); - } else { - PrintDebug("\t\tirq is disabled\n"); - } - - return; -} - -static void rd_lower_irq(struct vm_device *dev, Bit32u irq) // __attribute__(regparm(1)) -{ - PrintDebug("[lower_irq] irq = %d\n", irq); - dev->vm->vm_ops.lower_irq(dev->vm, irq); -} - - - - - - - -////////////////////////////////////////////////////////////////////////// - -/* - * ATAPI subroutines - */ - - - -int handle_atapi_packet_command(struct vm_device * dev, struct channel_t * channel, ushort_t value) { - struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data); - struct drive_t * drive = get_selected_drive(channel); - struct controller_t * controller = &(drive->controller); - - if (controller->buffer_index >= PACKET_SIZE) { - PrintError("ATAPI packet exceeded maximum length: buffer_index (%d) >= PACKET_SIZE\n", - controller->buffer_index); - return -1; - } - - controller->buffer[controller->buffer_index] = value; - controller->buffer[controller->buffer_index + 1] = (value >> 8); - controller->buffer_index += 2; - - - /* if packet completely writtten */ - if (controller->buffer_index >= PACKET_SIZE) { - // complete command received - Bit8u atapi_command = controller->buffer[0]; - - PrintDebug("\t\tcdrom: ATAPI command 0x%x started\n", atapi_command); - - switch (atapi_command) { - case 0x00: // test unit ready - { - if (drive->cdrom.ready) { - rd_atapi_cmd_nop(dev, channel); - } else { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - - rd_raise_interrupt(dev, channel); - - break; - } - case 0x03: // request sense - { - int alloc_length = controller->buffer[4]; - - if (rd_init_send_atapi_command(dev, channel, atapi_command, 18, alloc_length, false) == -1) { - return -1; - } - - // sense data - controller->buffer[0] = 0x70 | (1 << 7); - controller->buffer[1] = 0; - controller->buffer[2] = drive->sense.sense_key; - controller->buffer[3] = drive->sense.information.arr[0]; - controller->buffer[4] = drive->sense.information.arr[1]; - controller->buffer[5] = drive->sense.information.arr[2]; - controller->buffer[6] = drive->sense.information.arr[3]; - controller->buffer[7] = 17 - 7; - controller->buffer[8] = drive->sense.specific_inf.arr[0]; - controller->buffer[9] = drive->sense.specific_inf.arr[1]; - controller->buffer[10] = drive->sense.specific_inf.arr[2]; - controller->buffer[11] = drive->sense.specific_inf.arr[3]; - controller->buffer[12] = drive->sense.asc; - controller->buffer[13] = drive->sense.ascq; - controller->buffer[14] = drive->sense.fruc; - controller->buffer[15] = drive->sense.key_spec.arr[0]; - controller->buffer[16] = drive->sense.key_spec.arr[1]; - controller->buffer[17] = drive->sense.key_spec.arr[2]; - - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x1b: // start stop unit - { - //bx_bool Immed = (controller->buffer[1] >> 0) & 1; - rd_bool LoEj = (controller->buffer[4] >> 1) & 1; - rd_bool Start = (controller->buffer[4] >> 0) & 1; - - // stop the disc - if ((!LoEj) && (!Start)) { - PrintError("FIXME: Stop disc not implemented\n"); - - rd_atapi_cmd_nop(dev, channel); - rd_raise_interrupt(dev, channel); - } else if (!LoEj && Start) { // start (spin up) the disc - - drive->cdrom.cd->start_cdrom(drive->private_data); - - PrintError("FIXME: ATAPI start disc not reading TOC\n"); - rd_atapi_cmd_nop(dev, channel); - rd_raise_interrupt(dev, channel); - } else if (LoEj && !Start) { // Eject the disc - rd_atapi_cmd_nop(dev, channel); - - if (drive->cdrom.ready) { - - drive->cdrom.cd->eject_cdrom(drive->private_data); - - drive->cdrom.ready = 0; - //bx_options.atadevice[channel][SLAVE_SELECTED(channel)].Ostatus->set(EJECTED); - //bx_gui->update_drive_status_buttons(); - } - rd_raise_interrupt(dev, channel); - } else { // Load the disc - // My guess is that this command only closes the tray, that's a no-op for us - rd_atapi_cmd_nop(dev, channel); - rd_raise_interrupt(dev, channel); - } - break; - } - case 0xbd: // mechanism status - { - uint16_t alloc_length = rd_read_16bit(controller->buffer + 8); - - if (alloc_length == 0) { - PrintError("Zero allocation length to MECHANISM STATUS not impl.\n"); - return -1; - } - - if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, alloc_length, false) == -1) { - return -1; - } - - controller->buffer[0] = 0; // reserved for non changers - controller->buffer[1] = 0; // reserved for non changers - - controller->buffer[2] = 0; // Current LBA (TODO!) - controller->buffer[3] = 0; // Current LBA (TODO!) - controller->buffer[4] = 0; // Current LBA (TODO!) - - controller->buffer[5] = 1; // one slot - - controller->buffer[6] = 0; // slot table length - controller->buffer[7] = 0; // slot table length - - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x5a: // mode sense - { - uint16_t alloc_length = rd_read_16bit(controller->buffer + 7); - - Bit8u PC = controller->buffer[2] >> 6; - Bit8u PageCode = controller->buffer[2] & 0x3f; - - switch (PC) { - case 0x0: // current values - { - switch (PageCode) { - case 0x01: // error recovery - { - - if (rd_init_send_atapi_command(dev, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false) == -1) { - return -1; - } - - rd_init_mode_sense_single(dev, channel, &(drive->cdrom.current.error_recovery), - sizeof(struct error_recovery_t)); - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x2a: // CD-ROM capabilities & mech. status - { - - if (rd_init_send_atapi_command(dev, channel, atapi_command, 28, alloc_length, false) == -1) { - return -1; - } - - rd_init_mode_sense_single(dev, channel, &(controller->buffer[8]), 28); - - controller->buffer[8] = 0x2a; - controller->buffer[9] = 0x12; - controller->buffer[10] = 0x00; - controller->buffer[11] = 0x00; - // Multisession, Mode 2 Form 2, Mode 2 Form 1 - controller->buffer[12] = 0x70; - controller->buffer[13] = (3 << 5); - controller->buffer[14] = (unsigned char) (1 | - (drive->cdrom.locked ? (1 << 1) : 0) | - (1 << 3) | - (1 << 5)); - controller->buffer[15] = 0x00; - controller->buffer[16] = (706 >> 8) & 0xff; - controller->buffer[17] = 706 & 0xff; - controller->buffer[18] = 0; - controller->buffer[19] = 2; - controller->buffer[20] = (512 >> 8) & 0xff; - controller->buffer[21] = 512 & 0xff; - controller->buffer[22] = (706 >> 8) & 0xff; - controller->buffer[23] = 706 & 0xff; - controller->buffer[24] = 0; - controller->buffer[25] = 0; - controller->buffer[26] = 0; - controller->buffer[27] = 0; - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x3f: // all - { - PrintError("Ramdisk: cdrom: MODE SENSE (curr), code=%x not implemented yet\n", - PageCode); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - default: - { - // not implemeted by this device - PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - } - break; - } - case 0x1: // changeable values - { - switch (PageCode) { - case 0x01: // error recovery - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x2a: // CD-ROM capabilities & mech. status - case 0x3f: // all - { - PrintError("cdrom: MODE SENSE (chg), code=%x not implemented yet\n", - PageCode); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - default: - { - // not implemeted by this device - PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - } - break; - } - case 0x2: // default values - { - switch (PageCode) { - case 0x01: // error recovery - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x2a: // CD-ROM capabilities & mech. status - case 0x3f: // all - PrintError("cdrom: MODE SENSE (dflt), code=%x\n", - PageCode); - return -1; - - default: - { - // not implemeted by this device - PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - } - break; - } - case 0x3: // saved values not implemented - { - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); - rd_raise_interrupt(dev, channel); - break; - } - default: - { - PrintError("Should not get here!\n"); - return -1; - break; - } - } - break; - } - case 0x12: // inquiry - { - uint8_t alloc_length = controller->buffer[4]; - - if (rd_init_send_atapi_command(dev, channel, atapi_command, 36, alloc_length, false) == -1) { - return -1; - } - - controller->buffer[0] = 0x05; // CD-ROM - controller->buffer[1] = 0x80; // Removable - controller->buffer[2] = 0x00; // ISO, ECMA, ANSI version - controller->buffer[3] = 0x21; // ATAPI-2, as specified - controller->buffer[4] = 31; // additional length (total 36) - controller->buffer[5] = 0x00; // reserved - controller->buffer[6] = 0x00; // reserved - controller->buffer[7] = 0x00; // reserved - - // Vendor ID - const char* vendor_id = "VTAB "; - int i; - for (i = 0; i < 8; i++) { - controller->buffer[8+i] = vendor_id[i]; - } - - // Product ID - const char* product_id = "Turbo CD-ROM "; - for (i = 0; i < 16; i++) { - controller->buffer[16+i] = product_id[i]; - } - - // Product Revision level - const char* rev_level = "1.0 "; - for (i = 0; i < 4; i++) { - controller->buffer[32 + i] = rev_level[i]; - } - - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x25: // read cd-rom capacity - { - // no allocation length??? - if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, 8, false) == -1) { - return -1; - } - - if (drive->cdrom.ready) { - uint32_t capacity = drive->cdrom.capacity; - PrintDebug("\t\tCapacity is %d sectors (%d bytes)\n", capacity, capacity * 2048); - - controller->buffer[0] = (capacity >> 24) & 0xff; - controller->buffer[1] = (capacity >> 16) & 0xff; - controller->buffer[2] = (capacity >> 8) & 0xff; - controller->buffer[3] = (capacity >> 0) & 0xff; - controller->buffer[4] = (2048 >> 24) & 0xff; - controller->buffer[5] = (2048 >> 16) & 0xff; - controller->buffer[6] = (2048 >> 8) & 0xff; - controller->buffer[7] = (2048 >> 0) & 0xff; - - rd_ready_to_send_atapi(dev, channel); - } else { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - } - break; - } - - - case 0xbe: // read cd - { - if (drive->cdrom.ready) { - PrintError("Read CD with CD present not implemented\n"); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - } else { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - } - break; - } - case 0x43: // read toc - { - if (drive->cdrom.ready) { - int toc_length; - bool msf = (controller->buffer[1] >> 1) & 1; - uint8_t starting_track = controller->buffer[6]; - - uint16_t alloc_length = rd_read_16bit(controller->buffer + 7); - - uint8_t format = (controller->buffer[9] >> 6); - int i; - switch (format) { - case 0: - - if (!(drive->cdrom.cd->read_toc(drive->private_data, controller->buffer, - &toc_length, msf, starting_track))) { - PrintDebug("CDROM: Reading Table of Contents Failed\n"); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - } else { - if (rd_init_send_atapi_command(dev, channel, atapi_command, toc_length, alloc_length, false) == -1) { - return -1; - } - rd_ready_to_send_atapi(dev, channel); - } - break; - - case 1: - // multi session stuff. we ignore this and emulate a single session only - if (rd_init_send_atapi_command(dev, channel, atapi_command, 12, alloc_length, false) == -1) { - return -1; - } - - controller->buffer[0] = 0; - controller->buffer[1] = 0x0a; - controller->buffer[2] = 1; - controller->buffer[3] = 1; - - for (i = 0; i < 8; i++) { - controller->buffer[4 + i] = 0; - } - - rd_ready_to_send_atapi(dev, channel); - break; - - case 2: - default: - PrintError("(READ TOC) Format %d not supported\n", format); - return -1; - } - } else { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - } - break; - } - case 0x28: // read (10) - case 0xa8: // read (12) - { - - uint32_t transfer_length; - if (atapi_command == 0x28) { - transfer_length = rd_read_16bit(controller->buffer + 7); - } else { - transfer_length = rd_read_32bit(controller->buffer + 6); - } - - uint32_t lba = rd_read_32bit(controller->buffer + 2); - - if (!(drive->cdrom.ready)) { - PrintError("CDROM Error: Not Ready (ATA%d/%d)\n", - get_channel_no(ramdisk, channel), get_drive_no(channel, drive)); - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - break; - } - - if (transfer_length == 0) { - rd_atapi_cmd_nop(dev, channel); - rd_raise_interrupt(dev, channel); - PrintError("READ(%d) with transfer length 0, ok\n", - (atapi_command == 0x28) ? 10 : 12); - break; - } - - if (lba + transfer_length > drive->cdrom.capacity) { - PrintError("CDROM Error: Capacity exceeded [capacity=%d] (ATA%d/%d)\n", - drive->cdrom.capacity, - get_channel_no(ramdisk, channel), get_drive_no(channel, drive)); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - rd_raise_interrupt(dev, channel); - break; - } - - PrintDebug("\t\tcdrom: READ (%d) LBA=%d LEN=%d\n", - (atapi_command == 0x28) ? 10 : 12, - lba, transfer_length); - - // handle command - if (rd_init_send_atapi_command(dev, channel, atapi_command, transfer_length * 2048, - transfer_length * 2048, true) == -1) { - PrintError("CDROM Error: Atapi command send error\n"); - return -1; - } - - drive->cdrom.remaining_blocks = transfer_length; - drive->cdrom.next_lba = lba; - rd_ready_to_send_atapi(dev, channel); - break; - } - case 0x2b: // seek - { - uint32_t lba = rd_read_32bit(controller->buffer + 2); - - if (!(drive->cdrom.ready)) { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - break; - } - - if (lba > drive->cdrom.capacity) { - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - rd_raise_interrupt(dev, channel); - break; - } - - PrintDebug("\t\tcdrom: SEEK (ignored)\n"); - - rd_atapi_cmd_nop(dev, channel); - rd_raise_interrupt(dev, channel); - - break; - } - case 0x1e: // prevent/allow medium removal - { - - if (drive->cdrom.ready) { - drive->cdrom.locked = controller->buffer[4] & 1; - rd_atapi_cmd_nop(dev, channel); - } else { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - - rd_raise_interrupt(dev, channel); - - break; - } - case 0x42: // read sub-channel - { - //bool msf = get_packet_field(channel,1, 1, 1); - bool sub_q = get_packet_field(channel,2, 6, 1); - //uint8_t data_format = get_packet_byte(channel,3); - //uint8_t track_number = get_packet_byte(channel,6); - uint16_t alloc_length = get_packet_word(channel,7); - - - /* - UNUSED(msf); - UNUSED(data_format); - UNUSED(track_number); - */ - if (!(drive->cdrom.ready)) { - rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(dev, channel); - } else { - controller->buffer[0] = 0; - controller->buffer[1] = 0; // audio not supported - controller->buffer[2] = 0; - controller->buffer[3] = 0; - - int ret_len = 4; // header size - - if (sub_q) { // !sub_q == header only - PrintError("Read sub-channel with SubQ not implemented\n"); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - } - - if (rd_init_send_atapi_command(dev, channel, atapi_command, ret_len, alloc_length, false) == -1) { - return -1; - } - rd_ready_to_send_atapi(dev, channel); - } - break; - } - case 0x51: // read disc info - { - // no-op to keep the Linux CD-ROM driver happy - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - } - case 0x55: // mode select - case 0xa6: // load/unload cd - case 0x4b: // pause/resume - case 0x45: // play audio - case 0x47: // play audio msf - case 0xbc: // play cd - case 0xb9: // read cd msf - case 0x44: // read header - case 0xba: // scan - case 0xbb: // set cd speed - case 0x4e: // stop play/scan - case 0x46: // ??? - case 0x4a: // ??? - PrintError("ATAPI command 0x%x not implemented yet\n", - atapi_command); - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; - default: - PrintError("Unknown ATAPI command 0x%x (%d)\n", - atapi_command, atapi_command); - // We'd better signal the error if the user chose to continue - rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(dev, channel); - break; + if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), + &blk_ops, frontend_cfg, disk) == -1) { + PrintError("Could not connect %s to frontend %s\n", + name, v3_cfg_val(frontend_cfg, "tag")); + return -1; } - } - return 0; -} - - - - -int rd_init_send_atapi_command(struct vm_device * dev, struct channel_t * channel, Bit8u command, int req_length, int alloc_length, bool lazy) -{ - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - - // controller->byte_count is a union of controller->cylinder_no; - // lazy is used to force a data read in the buffer at the next read. - - PrintDebug("[rd_init_send_atapi_cmd]\n"); - - if (controller->byte_count == 0xffff) { - controller->byte_count = 0xfffe; - } - - if ((controller->byte_count & 1) && - !(alloc_length <= controller->byte_count)) { - - PrintDebug("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n", - controller->byte_count, - command, - controller->byte_count - 1); - controller->byte_count -= 1; - } - - if (controller->byte_count == 0) { - PrintError("\t\tATAPI command with zero byte count\n"); - return -1; - } - - if (alloc_length < 0) { - PrintError("\t\tAllocation length < 0\n"); - return -1; - } - - if (alloc_length == 0) { - alloc_length = controller->byte_count; - } - - controller->interrupt_reason.i_o = 1; - controller->interrupt_reason.c_d = 0; - controller->status.busy = 0; - controller->status.drq = 1; - controller->status.err = 0; - - // no bytes transfered yet - if (lazy) { - controller->buffer_index = 2048; - } else { - controller->buffer_index = 0; - } - - controller->drq_index = 0; - - if (controller->byte_count > req_length) { - controller->byte_count = req_length; - } - - if (controller->byte_count > alloc_length) { - controller->byte_count = alloc_length; - } - - drive->atapi.command = command; - drive->atapi.drq_bytes = controller->byte_count; - drive->atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; - - // if (lazy) { - // // bias drq_bytes and total_bytes_remaining - // SELECTED_DRIVE(channel).atapi.drq_bytes += 2048; - // SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048; - // } - - return 0; -} - - - - void rd_ready_to_send_atapi(struct vm_device * dev, struct channel_t * channel) { - PrintDebug("[rd_ready_to_send_atapi]\n"); - - rd_raise_interrupt(dev, channel); -} - - - - - -void rd_atapi_cmd_error(struct vm_device * dev, struct channel_t * channel, sense_t sense_key, asc_t asc) -{ - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - -#ifdef DEBUG_RAMDISK - { - struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data); - PrintDebug("[rd_atapi_cmd_error]\n"); - PrintDebug("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n", - get_channel_no(ramdisk, channel), sense_key, asc); - } -#endif - - controller->error_register = sense_key << 4; - controller->interrupt_reason.i_o = 1; - controller->interrupt_reason.c_d = 1; - controller->interrupt_reason.rel = 0; - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.write_fault = 0; - controller->status.drq = 0; - controller->status.err = 1; - - drive->sense.sense_key = sense_key; - drive->sense.asc = asc; - drive->sense.ascq = 0; -} - - - -void rd_atapi_cmd_nop(struct vm_device * dev, struct channel_t * channel) -{ - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - - PrintDebug("[rd_atapi_cmd_nop]\n"); - controller->interrupt_reason.i_o = 1; - controller->interrupt_reason.c_d = 1; - controller->interrupt_reason.rel = 0; - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.drq = 0; - controller->status.err = 0; -} - - - - -void rd_identify_ATAPI_drive(struct vm_device * dev, struct channel_t * channel) -{ - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - - - uint_t i; - const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0"; - const char* firmware = "ALPHA1 "; - - drive->id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets - - for (i = 1; i <= 9; i++) { - drive->id_drive[i] = 0; - } - - for (i = 0; i < 10; i++) { - drive->id_drive[10 + i] = ((serial_number[i * 2] << 8) | - (serial_number[(i * 2) + 1])); - } - - for (i = 20; i <= 22; i++) { - drive->id_drive[i] = 0; - } - - for (i = 0; i < strlen(firmware)/2; i++) { - drive->id_drive[23 + i] = ((firmware[i * 2] << 8) | - (firmware[(i * 2) + 1])); - } - V3_ASSERT((23 + i) == 27); - - for (i = 0; i < strlen((char *)(drive->model_no)) / 2; i++) { - drive->id_drive[27 + i] = ((drive->model_no[i * 2] << 8) | - (drive->model_no[(i * 2) + 1])); - } - V3_ASSERT((27 + i) == 47); - - drive->id_drive[47] = 0; - drive->id_drive[48] = 1; // 32 bits access - - drive->id_drive[49] = (1 << 9); // LBA supported - - drive->id_drive[50] = 0; - drive->id_drive[51] = 0; - drive->id_drive[52] = 0; - drive->id_drive[53] = 3; // words 64-70, 54-58 valid - - for (i = 54; i <= 62; i++) { - drive->id_drive[i] = 0; - } - - // copied from CFA540A - drive->id_drive[63] = 0x0103; // variable (DMA stuff) - drive->id_drive[64] = 0x0001; // PIO - drive->id_drive[65] = 0x00b4; - drive->id_drive[66] = 0x00b4; - drive->id_drive[67] = 0x012c; - drive->id_drive[68] = 0x00b4; - - drive->id_drive[69] = 0; - drive->id_drive[70] = 0; - drive->id_drive[71] = 30; // faked - drive->id_drive[72] = 30; // faked - drive->id_drive[73] = 0; - drive->id_drive[74] = 0; - - drive->id_drive[75] = 0; - - for (i = 76; i <= 79; i++) { - drive->id_drive[i] = 0; - } - - drive->id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 - drive->id_drive[81] = 0; - drive->id_drive[82] = 0; - drive->id_drive[83] = 0; - drive->id_drive[84] = 0; - drive->id_drive[85] = 0; - drive->id_drive[86] = 0; - drive->id_drive[87] = 0; - drive->id_drive[88] = 0; - - for (i = 89; i <= 126; i++) { - drive->id_drive[i] = 0; - } - - drive->id_drive[127] = 0; - drive->id_drive[128] = 0; - - for (i = 129; i <= 159; i++) { - drive->id_drive[i] = 0; - } - - for (i = 160; i <= 255; i++) { - drive->id_drive[i] = 0; - } - - // now convert the id_drive array (native 256 word format) to - // the controller buffer (512 bytes) - Bit16u temp16; - for (i = 0; i <= 255; i++) { - temp16 = drive->id_drive[i]; - controller->buffer[i * 2] = temp16 & 0x00ff; - controller->buffer[i * 2 + 1] = temp16 >> 8; - } - - return; -} - - - - - - - -static -void rd_init_mode_sense_single(struct vm_device * dev, - struct channel_t * channel, const void* src, int size) -{ - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - - PrintDebug("[rd_init_mode_sense_single]\n"); - - // Header - controller->buffer[0] = (size + 6) >> 8; - controller->buffer[1] = (size + 6) & 0xff; - controller->buffer[2] = 0x70; // no media present - controller->buffer[3] = 0; // reserved - controller->buffer[4] = 0; // reserved - controller->buffer[5] = 0; // reserved - controller->buffer[6] = 0; // reserved - controller->buffer[7] = 0; // reserved - - // Data - memcpy(controller->buffer + 8, src, size); -} - - - -static void rd_command_aborted(struct vm_device * dev, - struct channel_t * channel, unsigned value) { - struct drive_t * drive = &(channel->drives[channel->drive_select]); - struct controller_t * controller = &(drive->controller); - - PrintDebug("[rd_command_aborted]\n"); - PrintDebug("\t\taborting on command 0x%02x {%s}\n", value, device_type_to_str(drive->device_type)); - - controller->current_command = 0; - controller->status.busy = 0; - controller->status.drive_ready = 1; - controller->status.err = 1; - controller->error_register = 0x04; // command ABORTED - controller->status.drq = 0; - controller->status.seek_complete = 0; - controller->status.corrected_data = 0; - controller->buffer_index = 0; - - rd_raise_interrupt(dev, channel); -} - - -static int ramdisk_init_device(struct vm_device *dev) { - struct ramdisk_t *ramdisk= (struct ramdisk_t *)dev->private_data; - - PrintDebug("Initializing Ramdisk\n"); - - - rd_init_hardware(ramdisk); - - - dev_hook_io(dev, PRI_CTRL_PORT, - &read_status_port, &write_ctrl_port); - - dev_hook_io(dev, PRI_DATA_PORT, - &read_data_port, &write_data_port); - dev_hook_io(dev, PRI_FEATURES_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_SECT_CNT_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_SECT_ADDR1_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_SECT_ADDR2_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_SECT_ADDR3_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_DRV_SEL_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, PRI_CMD_PORT, - &read_status_port, &write_cmd_port); - - - dev_hook_io(dev, SEC_CTRL_PORT, - &read_status_port, &write_ctrl_port); - - dev_hook_io(dev, SEC_DATA_PORT, - &read_data_port, &write_data_port); - dev_hook_io(dev, SEC_FEATURES_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_SECT_CNT_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_SECT_ADDR1_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_SECT_ADDR2_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_SECT_ADDR3_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_DRV_SEL_PORT, - &read_general_port, &write_general_port); - dev_hook_io(dev, SEC_CMD_PORT, - &read_status_port, &write_cmd_port); - - - - dev_hook_io(dev, SEC_ADDR_REG_PORT, - &read_general_port, &write_general_port); - - dev_hook_io(dev, PRI_ADDR_REG_PORT, - &read_general_port, &write_general_port); - - - - return 0; - -} - - -static int ramdisk_deinit_device(struct vm_device *dev) { - struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data); - rd_close_harddrive(ramdisk); - return 0; -} - -static struct vm_device_ops dev_ops = { - .init = ramdisk_init_device, - .deinit = ramdisk_deinit_device, - .reset = NULL, - .start = NULL, - .stop = NULL, -}; - - - - -struct vm_device *create_ramdisk() -{ - - struct ramdisk_t *ramdisk; - ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t)); - V3_ASSERT(ramdisk != NULL); - - PrintDebug("[create_ramdisk]\n"); - - struct vm_device *device = create_device("RAMDISK", &dev_ops, ramdisk); - - return device; -} - - - - -#ifdef DEBUG_RAMDISK - -static void rd_print_state(struct ramdisk_t * ramdisk) { - uchar_t channel; - uchar_t device; - struct channel_t * channels = (struct channel_t *)(&(ramdisk->channels)); - - /* - for (channel = 0; channel < MAX_ATA_CHANNEL; channel++) { - memset((char *)(channels + channel), 0, sizeof(struct channel_t)); - } - */ - PrintDebug("sizeof(*channels) = %d\n", sizeof(*channels)); - PrintDebug("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller))); - PrintDebug("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom))); - PrintDebug("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense))); - PrintDebug("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi))); - - - PrintDebug("sizeof(channles->drives[0].controller.status) = %d\n", - sizeof((channels->drives[0].controller.status))); - PrintDebug("sizeof(channles->drives[0].controller.sector_count) = %d\n", - sizeof((channels->drives[0].controller.sector_count))); - PrintDebug("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n", - sizeof((channels->drives[0].controller.interrupt_reason))); - - PrintDebug("sizeof(channles->drives[0].controller.cylinder_no) = %d\n", - sizeof((channels->drives[0].controller.cylinder_no))); - PrintDebug("sizeof(channles->drives[0].controller.byte_count) = %d\n", - sizeof((channels->drives[0].controller.byte_count))); - - - PrintDebug("sizeof(channles->drives[0].controller.control) = %d\n", - sizeof((channels->drives[0].controller.control))); - - - for (channel = 0; channel < MAX_ATA_CHANNEL; channel++){ - - for (device = 0; device < 2; device++){ - - // Initialize controller state, even if device is not present - PrintDebug("channels[%d].drives[%d].controller.status.busy = %d\n", - channel, device, - channels[channel].drives[device].controller.status.busy); - PrintDebug("channels[%d].drives[%d].controller.status.drive_ready = %d\n", - channel, device, - channels[channel].drives[device].controller.status.drive_ready); - PrintDebug("channels[%d].drives[%d].controller.status.write_fault = %d\n", - channel, device, - channels[channel].drives[device].controller.status.write_fault); - PrintDebug("channels[%d].drives[%d].controller.status.seek_complete = %d\n", - channel, device, - channels[channel].drives[device].controller.status.seek_complete); - PrintDebug("channels[%d].drives[%d].controller.status.drq = %d\n", - channel, device, - channels[channel].drives[device].controller.status.drq); - PrintDebug("channels[%d].drives[%d].controller.status.corrected_data = %d\n", - channel, device, - channels[channel].drives[device].controller.status.corrected_data); - PrintDebug("channels[%d].drives[%d].controller.status.index_pulse = %d\n", - channel, device, - channels[channel].drives[device].controller.status.index_pulse); - PrintDebug("channels[%d].drives[%d].controller.status.index_pulse_count = %d\n", - channel, device, - channels[channel].drives[device].controller.status.index_pulse_count); - PrintDebug("channels[%d].drives[%d].controller.status.err = %d\n", - channel, device, - channels[channel].drives[device].controller.status.err); - - - PrintDebug("channels[%d].drives[%d].controller.error_register = %d\n", - channel, device, - channels[channel].drives[device].controller.error_register); - PrintDebug("channels[%d].drives[%d].controller.head_no = %d\n", - channel, device, - channels[channel].drives[device].controller.head_no); - PrintDebug("channels[%d].drives[%d].controller.sector_count = %d\n", - channel, device, - channels[channel].drives[device].controller.sector_count); - PrintDebug("channels[%d].drives[%d].controller.sector_no = %d\n", - channel, device, - channels[channel].drives[device].controller.sector_no); - PrintDebug("channels[%d].drives[%d].controller.cylinder_no = %d\n", - channel, device, - channels[channel].drives[device].controller.cylinder_no); - PrintDebug("channels[%d].drives[%d].controller.current_command = %02x\n", - channel, device, - channels[channel].drives[device].controller.current_command); - PrintDebug("channels[%d].drives[%d].controller.buffer_index = %d\n", - channel, device, - channels[channel].drives[device].controller.buffer_index); - - - PrintDebug("channels[%d].drives[%d].controller.control.reset = %d\n", - channel, device, - channels[channel].drives[device].controller.control.reset); - PrintDebug("channels[%d].drives[%d].controller.control.disable_irq = %d\n", - channel, device, - channels[channel].drives[device].controller.control.disable_irq); - - - PrintDebug("channels[%d].drives[%d].controller.reset_in_progress = %d\n", - channel, device, - channels[channel].drives[device].controller.reset_in_progress); - PrintDebug("channels[%d].drives[%d].controller.sectors_per_block = %02x\n", - channel, device, - channels[channel].drives[device].controller.sectors_per_block); - PrintDebug("channels[%d].drives[%d].controller.lba_mode = %d\n", - channel, device, - channels[channel].drives[device].controller.lba_mode); - PrintDebug("channels[%d].drives[%d].controller.features = %d\n", - channel, device, - channels[channel].drives[device].controller.features); - - - PrintDebug("channels[%d].drives[%d].model_no = %s\n", - channel, device, - channels[channel].drives[device].model_no); - PrintDebug("channels[%d].drives[%d].device_type = %d\n", - channel, device, - channels[channel].drives[device].device_type); - PrintDebug("channels[%d].drives[%d].cdrom.locked = %d\n", - channel, device, - channels[channel].drives[device].cdrom.locked); - PrintDebug("channels[%d].drives[%d].sense.sense_key = %d\n", - channel, device, - channels[channel].drives[device].sense.sense_key); - PrintDebug("channels[%d].drives[%d].sense.asc = %d\n", - channel, device, - channels[channel].drives[device].sense.asc); - PrintDebug("channels[%d].drives[%d].sense.ascq = %d\n", - channel, device, - channels[channel].drives[device].sense.ascq); - - - - PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n", - channel, device, - channels[channel].drives[device].controller.interrupt_reason.c_d); - - PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n", - channel, device, - channels[channel].drives[device].controller.interrupt_reason.i_o); - - PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n", - channel, device, - channels[channel].drives[device].controller.interrupt_reason.rel); - - PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n", - channel, device, - channels[channel].drives[device].controller.interrupt_reason.tag); - - PrintDebug("channels[%d].drives[%d].cdrom.ready = %d\n", - channel, device, - channels[channel].drives[device].cdrom.ready); - - } //for device - } //for channel - - return; -} - -#if 0 -static void trace_info(ushort_t port, void *src, uint_t length) { - - switch(port){ - - case 0x3e8: - if (length == 1 && *((uchar_t*) src) == ATA_DETECT) - PrintDebug("ata_detect()\n"); - break; - - case 0x3e9: - if (length == 1 && *((uchar_t*) src) == ATA_RESET) - PrintDebug("ata_reset()\n"); - break; - - case 0x3ea: - if (length == 1 && *((uchar_t*) src) == ATA_CMD_DATA_IN) - PrintDebug("ata_cmd_data_in()\n"); - break; - - case 0x3eb: - if (length == 1 && *((uchar_t*) src) == ATA_CMD_DATA_OUT) - PrintDebug("ata_cmd_data_out()\n"); - break; - - case 0x3ec: - if (length == 1 && *((uchar_t*) src) == ATA_CMD_PACKET) - PrintDebug("ata_cmd_packet()\n"); - break; - - case 0x3ed: - if (length == 1 && *((uchar_t*) src) == ATAPI_GET_SENSE) - PrintDebug("atapi_get_sense()\n"); - break; - - case 0x3ee: - if (length == 1 && *((uchar_t*) src) == ATAPI_IS_READY) - PrintDebug("atapi_is_ready()\n"); - break; - - case 0x3ef: - if (length == 1 && *((uchar_t*) src) == ATAPI_IS_CDROM) - PrintDebug("atapi_is_cdrom()\n"); - break; - - - case 0x2e8: - if (length == 1 && *((uchar_t*) src) == CDEMU_INIT) - PrintDebug("cdemu_init()\n"); - break; - - case 0x2e9: - if (length == 1 && *((uchar_t*) src) == CDEMU_ISACTIVE) - PrintDebug("cdemu_isactive()\n"); - break; - - case 0x2ea: - if (length == 1 && *((uchar_t*) src) == CDEMU_EMULATED_DRIVE) - PrintDebug("cdemu_emulated_drive()\n"); - break; - - case 0x2eb: - if (length == 1 && *((uchar_t*) src) == CDROM_BOOT) - PrintDebug("cdrom_boot()\n"); - break; - - case 0x2ec: - if (length == 1 && *((uchar_t*) src) == HARD_DRIVE_POST) - PrintDebug("ata_hard_drive_post()\n"); - break; - - case 0x2ed: - if (length == 1) - PrintDebug("ata_device_no(%d)\n", *((uchar_t*) src)); - break; - - case 0x2ee: - if (length == 1) - PrintDebug("ata_device_type(%d)\n", *((uchar_t*) src)); - break; - - case 0x2ef: - if (length == 1 && *((uchar_t*) src) == INT13_HARDDISK) - PrintDebug("int13_harddrive()\n"); - break; - - case 0x2f8: - if (length == 1 && *((uchar_t*) src) == INT13_CDROM) - PrintDebug("int13_cdrom()\n"); - break; - - case 0x2f9: - if (length == 1 && *((uchar_t*) src) == INT13_CDEMU) - PrintDebug("int13_cdemu()\n"); - break; - - case 0x2fa: - if (length == 1 && *((uchar_t*) src) == INT13_ELTORITO) - PrintDebug("int13_eltorito()\n"); - break; - - case 0x2fb: - if (length == 1 && *((uchar_t*) src) == INT13_DISKETTE_FUNCTION) - PrintDebug("int13_diskette_function()\n"); - break; - - - default: - break; - } + return 0; } -#endif -static int check_bit_fields(struct controller_t * controller) { - //Check bit fields - controller->sector_count = 0; - controller->interrupt_reason.c_d = 1; - if (controller->sector_count != 0x01) { - return INTR_REASON_BIT_ERR; - } - - controller->sector_count = 0; - controller->interrupt_reason.i_o = 1; - if (controller->sector_count != 0x02) { - return INTR_REASON_BIT_ERR; - } - - controller->sector_count = 0; - controller->interrupt_reason.rel = 1; - if (controller->sector_count != 0x04) { - return INTR_REASON_BIT_ERR; - } - - controller->sector_count = 0; - controller->interrupt_reason.tag = 3; - if (controller->sector_count != 0x18) { - return INTR_REASON_BIT_ERR; - } - - return 0; -} -#endif +device_register("RAMDISK", disk_init)