From: Jack Lange Date: Wed, 18 Mar 2009 18:28:52 +0000 (-0500) Subject: added standard port write handler X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=ee9c51d03e9eaa875e45febd3fc8b695d1061956 added standard port write handler --- diff --git a/palacios/src/devices/ide-types.h b/palacios/src/devices/ide-types.h index 5509a96..2570a45 100644 --- a/palacios/src/devices/ide-types.h +++ b/palacios/src/devices/ide-types.h @@ -86,6 +86,12 @@ struct ide_drive_ctrl_reg { } __attribute__((packed)); +struct ide_features_reg { + union { + uint8_t val; + } __attribute__((packed)); +} __attribute__((packed)); + typedef enum { READ_SECT_W_RETRY = 0x20, diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c index 283d699..7e98d27 100644 --- a/palacios/src/devices/ide.c +++ b/palacios/src/devices/ide.c @@ -64,11 +64,23 @@ static inline const char * device_type_to_str(ide_dev_type_t type) { struct ide_drive { // Command Registers - uint8_t data_port; // 0x1f0,0x170 + + ide_dev_type_t drive_type; + +}; + + + +struct ide_channel { + struct ide_drive drives[2]; + + // Command Registers struct ide_error_reg error_reg; // [read] 0x1f1,0x171 uint8_t sector_count; // 0x1f2,0x172 uint8_t sector_num; // 0x1f3,0x173 + struct ide_features_reg features; + union { uint16_t cylinder; struct { @@ -82,22 +94,8 @@ struct ide_drive { struct ide_status_reg status; // [read] 0x1f7,0x177 uint8_t command_reg; // [write] 0x1f7,0x177 - // Control Registers struct ide_drive_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376 - - - - ide_dev_type_t drive_type; - -}; - - - -struct ide_channel { - struct ide_drive drives[2]; - - int drive_sel; }; @@ -127,7 +125,12 @@ static inline struct ide_channel * get_selected_channel(struct ide_internal * id } static inline struct ide_drive * get_selected_drive(struct ide_channel * channel) { - return &(channel->drives[channel->drive_sel]); + return &(channel->drives[channel->drive_head.drive_sel]); +} + + +static inline int is_lba_enabled(struct ide_channel * channel) { + return channel->drive_head.lba_mode; } @@ -150,8 +153,70 @@ static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_de } static int write_port_std(ushort_t port, void * src, uint_t length, struct vm_device * dev) { + struct ide_internal * ide = (struct ide_internal *)(dev->private_data); + struct ide_channel * channel = get_selected_channel(ide, port); + // struct ide_drive * drive = get_selected_drive(channel); + + if (length != 1) { + PrintError("Invalid Write length on IDE port %x\n", port); + return -1; + } + PrintDebug("IDE: Writing Standard Port %x (val=%x)\n", port, *(uint8_t *)src); - return -1; + + + switch (port) { + // reset and interrupt enable + case PRI_CTRL_PORT: + case SEC_CTRL_PORT: + channel->ctrl_reg.val = *(uint8_t *)src; + + if (channel->ctrl_reg.soft_reset) { + //reset_channel(channel); + return -1; + } + break; + + case PRI_FEATURES_PORT: + case SEC_FEATURES_PORT: + channel->features.val = *(uint8_t *)src; + break; + + case PRI_SECT_CNT_PORT: + case SEC_SECT_CNT_PORT: + channel->sector_count = *(uint8_t *)src; + break; + + case PRI_SECT_NUM_PORT: + case SEC_SECT_NUM_PORT: + channel->sector_num = *(uint8_t *)src; + + case PRI_CYL_LOW_PORT: + case SEC_CYL_LOW_PORT: + channel->cylinder_low = *(uint8_t *)src; + break; + + case PRI_CYL_HIGH_PORT: + case SEC_CYL_HIGH_PORT: + channel->cylinder_high = *(uint8_t *)src; + break; + + case PRI_DRV_SEL_PORT: + case SEC_DRV_SEL_PORT: + channel->drive_head.val = *(uint8_t *)src; + + // make sure the reserved bits are ok.. + // JRL TODO: check with new ramdisk to make sure this is right... + channel->drive_head.val |= 0xa0; + + + return -1; + + default: + PrintError("IDE: Write to unknown Port %x\n", port); + return -1; + } + return length; } @@ -193,33 +258,33 @@ static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_dev // This is really the error register. case PRI_FEATURES_PORT: case SEC_FEATURES_PORT: - *(uint8_t *)dst = drive->error_reg.val; + *(uint8_t *)dst = channel->error_reg.val; break; case PRI_SECT_CNT_PORT: case SEC_SECT_CNT_PORT: - *(uint8_t *)dst = drive->sector_count; + *(uint8_t *)dst = channel->sector_count; break; case PRI_SECT_NUM_PORT: case SEC_SECT_NUM_PORT: - *(uint8_t *)dst = drive->sector_num; + *(uint8_t *)dst = channel->sector_num; break; case PRI_CYL_LOW_PORT: case SEC_CYL_LOW_PORT: - *(uint8_t *)dst = drive->cylinder_low; + *(uint8_t *)dst = channel->cylinder_low; break; case PRI_CYL_HIGH_PORT: case SEC_CYL_HIGH_PORT: - *(uint8_t *)dst = drive->cylinder_high; + *(uint8_t *)dst = channel->cylinder_high; break; case PRI_DRV_SEL_PORT: case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6 - *(uint8_t *)dst = drive->drive_head.val; + *(uint8_t *)dst = channel->drive_head.val; break; case PRI_CTRL_PORT: @@ -227,7 +292,7 @@ static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_dev case PRI_CMD_PORT: case SEC_CMD_PORT: // Something about lowering interrupts here.... - *(uint8_t *)dst = drive->status.val; + *(uint8_t *)dst = channel->status.val; break; default: @@ -241,17 +306,7 @@ static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_dev static void init_drive(struct ide_drive * drive) { - drive->data_port = 0x00; - drive->error_reg.val = 0x01; - drive->sector_count = 0x01; - drive->sector_num = 0x01; - drive->cylinder = 0x0000; - drive->drive_head.val = 0x00; - drive->status.val = 0x00; - drive->command_reg = 0x00; - - drive->ctrl_reg.val = 0x08; drive->drive_type = IDE_NONE; @@ -260,11 +315,19 @@ static void init_drive(struct ide_drive * drive) { static void init_channel(struct ide_channel * channel) { int i = 0; + channel->error_reg.val = 0x01; + channel->sector_count = 0x01; + channel->sector_num = 0x01; + channel->cylinder = 0x0000; + channel->drive_head.val = 0x00; + channel->status.val = 0x00; + channel->command_reg = 0x00; + channel->ctrl_reg.val = 0x08; + for (i = 0; i < 2; i++) { init_drive(&(channel->drives[i])); } - channel->drive_sel = 0; } static void init_ide_state(struct ide_internal * ide) {