From: Jack Lange Date: Thu, 2 Oct 2008 05:51:05 +0000 (-0500) Subject: reworked ramdisk now compiles, not tested X-Git-Tag: 1.0~3^2~17^2~3 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=a1a2be8eb002e13b1eb6ccaca40e4396f8816402 reworked ramdisk now compiles, not tested --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index 734062b..5c6cc51 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -183,16 +183,6 @@ endif # TCPSTACK=UIP -# -#RAMDISK -# -RAMDISK_SRCS= -BOOT_FLAGS= - -ifeq ($(RAMDISK_BOOT),1) -BOOT_FLAGS := $(BOOT_FLAGS) -DRAMDISK_BOOT -RAMDISK_SRCS := ramdisk.c cdrom.c -endif @@ -295,7 +285,7 @@ VMM_OBJS := $(VMM_C_OBJS) $(VMM_ASM_OBJS) -DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c $(RAMDISK_SRCS) +DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c ramdisk.c cdrom.c DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o) diff --git a/palacios/include/devices/cdrom.h b/palacios/include/devices/cdrom.h index 4546f4f..fb49ad9 100644 --- a/palacios/include/devices/cdrom.h +++ b/palacios/include/devices/cdrom.h @@ -7,17 +7,12 @@ #ifndef __DEVICES_CDROM_H_ #define __DEVICES_CDROM_H_ -#include +#include +#include +#include + -typedef unsigned int rd_bool; -typedef uchar_t Bit8u; -typedef ushort_t Bit16u; -typedef uint_t Bit32u; -typedef ullong_t Bit64u; -#define uint8 Bit8u -#define uint16 Bit16u -#define uint32 Bit32u struct cdrom_interface; @@ -38,17 +33,17 @@ struct cdrom_ops { /* * Read CD TOC. Returns false if start track is out of bounds. */ - rd_bool (*read_toc)(struct cdrom_interface *cdrom, uint8* buf, int* length, rd_bool msf, int start_track); + rd_bool (*read_toc)(struct cdrom_interface * cdrom, uint8_t * buf, int* length, rd_bool msf, int start_track); /* * Return CD-ROM capacity (in 2048 byte frames) */ - uint32 (*capacity)(struct cdrom_interface *cdrom); + uint32_t (*capacity)(struct cdrom_interface *cdrom); /* * Read a single block from the CD */ - void (*read_block)(struct cdrom_interface *cdrom, uint8* buf, int lba); + void (*read_block)(struct cdrom_interface *cdrom, uint8_t* buf, int lba); /* * Start (spin up) the CD. diff --git a/palacios/include/devices/ramdisk.h b/palacios/include/devices/ramdisk.h index b5b7d66..77eb44d 100644 --- a/palacios/include/devices/ramdisk.h +++ b/palacios/include/devices/ramdisk.h @@ -7,12 +7,14 @@ #ifndef __DEVICES_RAMDISK_H_ #define __DEVICES_RAMDISK_H_ -#include //for off_t in C99 -#include //for size_t -#include -#include +#include #include + + + + + struct vm_device * create_ramdisk(void); #endif diff --git a/palacios/src/devices/cdrom.c b/palacios/src/devices/cdrom.c index cfcd7bb..61d7f52 100644 --- a/palacios/src/devices/cdrom.c +++ b/palacios/src/devices/cdrom.c @@ -56,7 +56,7 @@ void cdrom_eject(struct cdrom_interface *cdrom) * Read CD TOC. Returns false if start track is out of bounds. */ static -rd_bool cdrom_read_toc(struct cdrom_interface *cdrom, uint8* buf, int* length, rd_bool msf, int start_track) +rd_bool cdrom_read_toc(struct cdrom_interface *cdrom, uint8_t* buf, int* length, rd_bool msf, int start_track) { Ramdisk_Print_CD("[cdrom_read_toc]\n"); return 1; @@ -66,7 +66,7 @@ rd_bool cdrom_read_toc(struct cdrom_interface *cdrom, uint8* buf, int* length, r * Return CD-ROM capacity (in 2048 byte frames) */ static -uint32 cdrom_capacity(struct cdrom_interface *cdrom) +uint32_t cdrom_capacity(struct cdrom_interface *cdrom) { Ramdisk_Print_CD("[cdrom_capacity] s_ramdiskSize = %d\n", cdrom->capacity_B); if (cdrom->lba) { @@ -87,13 +87,13 @@ uint32 cdrom_capacity(struct cdrom_interface *cdrom) * Read a single block from the CD */ static -void cdrom_read_block(struct cdrom_interface *cdrom, uint8* buf, int lba)// __attribute__(regparm(2)); +void cdrom_read_block(struct cdrom_interface *cdrom, uint8_t* buf, int lba)// __attribute__(regparm(2)); { V3_ASSERT(lba != 0); Ramdisk_Print_CD("[cdrom_read_block] lba = %d\n", lba); - memcpy(buf, (uint8 *)(cdrom->fd + lba*2048), 2048); + memcpy(buf, (uint8_t *)(cdrom->fd + lba*2048), 2048); return; } diff --git a/palacios/src/devices/ramdisk.c b/palacios/src/devices/ramdisk.c index 3e21f7c..4324c15 100644 --- a/palacios/src/devices/ramdisk.c +++ b/palacios/src/devices/ramdisk.c @@ -6,7 +6,9 @@ #include #include -#include +#include +#include +#include #ifdef DEBUG_RAMDISK //#define Ramdisk_Print(_f, _a...) PrintTrace("\nramdisk.c(%d) " _f, __LINE__, ## _a) @@ -26,6 +28,9 @@ + + + /* * Data type definitions * @@ -33,7 +38,6 @@ #define INDEX_PULSE_CYCLE 10 #define MAX_ATA_CHANNEL 4 -#define RD_LITTLE_ENDIAN #define INTR_REASON_BIT_ERR 0x01 @@ -42,17 +46,35 @@ #define READ_BUF_GT_512 0x04 -typedef enum _sense { - SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5, - SENSE_UNIT_ATTENTION = 6 -} sense_t ; -typedef enum _asc { - ASC_INV_FIELD_IN_CMD_PACKET = 0x24, - ASC_MEDIUM_NOT_PRESENT = 0x3a, - ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39, - ASC_LOGICAL_BLOCK_OOR = 0x21 -} asc_t ; +#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 + // FLAT MODE @@ -78,194 +100,9 @@ ssize_t rd_read (void* buf, size_t count); ssize_t rd_write (const void* buf, size_t count); -typedef struct { - - unsigned cylinders ; - unsigned heads ; - unsigned sectors ; - - //iso file descriptor - int fd ; -} device_image_t; - - - -struct controller_t { - struct { - rd_bool busy ; - rd_bool drive_ready ; - rd_bool write_fault ; - rd_bool seek_complete ; - rd_bool drq ; - rd_bool corrected_data ; - rd_bool index_pulse ; - unsigned int index_pulse_count ; - rd_bool err ; - } status; - Bit8u error_register ; - Bit8u head_no ; - union { - Bit8u sector_count ; - struct { -#ifdef RD_LITTLE_ENDIAN - unsigned c_d : 1; - unsigned i_o : 1; - unsigned rel : 1; - unsigned tag : 5; - -#else /* RD_BIG_ENDIAN */ - unsigned tag : 5; - unsigned rel : 1; - unsigned i_o : 1; - unsigned c_d : 1; -#endif - - } interrupt_reason; - }; - Bit8u sector_no ; - union { - Bit16u cylinder_no ; - Bit16u byte_count ; - }; - Bit8u buffer[2048]; ; - Bit32u buffer_index ; - Bit32u drq_index ; - Bit8u current_command ; - Bit8u sectors_per_block ; - Bit8u lba_mode ; - struct { - // 0=normal, 1=reset controller - rd_bool reset ; - // 0=allow irq, 1=disable irq - rd_bool disable_irq ; - } control; - Bit8u reset_in_progress ; - Bit8u features ; - }; - -struct sense_info_t{ - sense_t sense_key ; - struct { - Bit8u arr[4] ; - } information; - struct { - Bit8u arr[4] ; - } specific_inf; - struct { - Bit8u arr[3] ; - } key_spec; - Bit8u fruc ; - Bit8u asc ; - Bit8u ascq ; -}; - -struct error_recovery_t { - unsigned char data[8] ; - - // error_recovery_t (); -}; - -uint16 rd_read_16bit(const uint8* buf); //__attribute__(regparm(1)) -uint32 rd_read_32bit(const uint8* buf); //__attribute__(regparm(1)) - -struct cdrom_t { - rd_bool ready ; - rd_bool locked ; - - - struct cdrom_interface *cd ; - - uint32 capacity ; - int next_lba ; - int remaining_blocks ; - struct currentStruct { - struct error_recovery_t error_recovery ; - } current; -}; - -struct atapi_t { - uint8 command ; - int drq_bytes ; - int total_bytes_remaining ; -}; - - -typedef enum { - IDE_NONE, IDE_DISK, IDE_CDROM -} device_type_t ; - - - // FIXME: - // For each ATA channel we should have one controller struct - // and an array of two drive structs -struct channel_t { - struct drive_t { - device_image_t hard_drive ; - device_type_t device_type ; - // 512 byte buffer for ID drive command - // These words are stored in native word endian format, as - // they are fetched and returned via a return(), so - // there's no need to keep them in x86 endian format. - Bit16u id_drive[256] ; - - struct controller_t controller ; - struct cdrom_t cdrom ; - struct sense_info_t sense ; - struct atapi_t atapi ; - - Bit8u model_no[41] ; - } drives[2]; - unsigned drive_select ; - - Bit16u ioaddr1 ; - Bit16u ioaddr2 ; - Bit8u irq ; -}; - -struct ramdisk_t; - -struct ramdisk_ctrl_ops { - Bit32u (*init)(struct ramdisk_t *ramdisk, - struct vm_device *dev); - void (*close)(struct ramdisk_t *ramdisk); - void (*reset)(struct ramdisk_t *ramdisk, unsigned type); - -}; - -struct ramdisk_emu_ops { - - int (*read_port)(ushort_t port, - void *dst, - uint_t length, - struct vm_device *dev); - - int (*write_port)(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev); - - int (*read_port_ignore)(ushort_t port, - void *dst, - uint_t length, - struct vm_device *dev); - - int (*write_port_ignore)(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev); -}; - struct ramdisk_t { - struct channel_t channels[MAX_ATA_CHANNEL]; - - struct ramdisk_ctrl_ops cops; - - struct ramdisk_emu_ops eops; - - void *private_data; - // struct vm_device *dev; }; @@ -300,405 +137,318 @@ struct ramdisk_t { #define INT13_ELTORITO 0xe2 //0x2fa #define INT13_DISKETTE_FUNCTION 0xe3 //0x2fb -// some packet handling macros -#define EXTRACT_FIELD(arr,byte,start,num_bits) (((arr)[(byte)] >> (start)) & ((1 << (num_bits)) - 1)) -#define get_packet_field(c,b,s,n) (EXTRACT_FIELD((SELECTED_CONTROLLER((c)).buffer),(b),(s),(n))) -#define get_packet_byte(c,b) (SELECTED_CONTROLLER((c)).buffer[(b)]) -#define get_packet_word(c,b) (((uint16)SELECTED_CONTROLLER((c)).buffer[(b)] << 8) | SELECTED_CONTROLLER((c)).buffer[(b)+1]) -#define CONTROLLER(c,a) (channels[(c)].drives[(a)]).controller -#define DRIVE(c,a) (channels[(c)].drives[(a)]) -#define SELECTED_CONTROLLER(c) (CONTROLLER((c), channels[(c)].drive_select)) -#define SELECTED_DRIVE(c) (DRIVE((c), channels[(c)].drive_select)) - - -#define DRIVE_IS_PRESENT(c,a) (channels[(c)].drives[(a)].device_type != IDE_NONE) -#define DRIVE_IS_HD(c,a) (channels[(c)].drives[(a)].device_type == IDE_DISK) -#define DRIVE_IS_CD(c,a) (channels[(c)].drives[(a)].device_type == IDE_CDROM) -#define SELECTED_MODEL(c) (channels[(c)].drives[channels[(c)].drive_select].model_no) - -#define MASTER_SELECTED(c) (!channels[(c)].drive_select) -#define SLAVE_SELECTED(c) (channels[(c)].drive_select) - -#define SELECTED_IS_PRESENT(c) (DRIVE_IS_PRESENT((c),SLAVE_SELECTED((c)))) -#define SELECTED_IS_HD(c) (DRIVE_IS_HD((c),SLAVE_SELECTED((c)))) -#define SELECTED_IS_CD(c) (DRIVE_IS_CD((c),SLAVE_SELECTED((c)))) - -#define ANY_IS_PRESENT(c) (DRIVE_IS_PRESENT((c),0) || DRIVE_IS_PRESENT((c),1)) -#define SELECTED_TYPE_STRING(channel) ((SELECTED_IS_CD(channel)) ? "CD-ROM" : "NONE") - -#define WRITE_FEATURES(c,a) do { uint8 _a = a; CONTROLLER((c),0).features = _a; CONTROLLER((c),1).features = _a; } while(0) -#define WRITE_SECTOR_COUNT(c,a) do { uint8 _a = a; CONTROLLER((c),0).sector_count = _a; CONTROLLER((c),1).sector_count = _a; } while(0) -#define WRITE_SECTOR_NUMBER(c,a) do { uint8 _a = a; CONTROLLER((c),0).sector_no = _a; CONTROLLER((c),1).sector_no = _a; } while(0) -#define WRITE_CYLINDER_LOW(c,a) do { uint8 _a = a; CONTROLLER((c),0).cylinder_no = (CONTROLLER((c),0).cylinder_no & 0xff00) | _a; CONTROLLER((c),1).cylinder_no = (CONTROLLER((c),1).cylinder_no & 0xff00) | _a; } while(0) -#define WRITE_CYLINDER_HIGH(c,a) do { uint16 _a = a; CONTROLLER((c),0).cylinder_no = (_a << 8) | (CONTROLLER((c),0).cylinder_no & 0xff); CONTROLLER((c),1).cylinder_no = (_a << 8) | (CONTROLLER((c),1).cylinder_no & 0xff); } while(0) -#define WRITE_HEAD_NO(c,a) do { uint8 _a = a; CONTROLLER((c),0).head_no = _a; CONTROLLER((c),1).head_no = _a; } while(0) -#define WRITE_LBA_MODE(c,a) do { uint8 _a = a; CONTROLLER((c),0).lba_mode = _a; CONTROLLER((c),1).lba_mode = _a; } while(0) - - - -#define GOTO_RETURN_VALUE if(io_len==4){\ - goto return_value32;\ - }\ - else if(io_len==2){\ - value16=(Bit16u)value32;\ - goto return_value16;\ - }\ - else{\ - value8=(Bit8u)value32;\ - goto return_value8;\ - } - -#define UNUSED(x) ((void)x) - -#define PACKET_SIZE 12 - -static struct ramdisk_t *ramdisk_state; - +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 routines - */ -static -int ramdisk_read_port(ushort_t port, - void *dst, - uint_t length, - struct vm_device *dev); +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 -int ramdisk_write_port(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev); +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 -int ramdisk_read_port_ignore(ushort_t port, - void *dst, - uint_t length, - struct vm_device *dev); -static -int ramdisk_write_port_ignore(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev); +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); -static -Bit32u rd_read_handler(struct channel_t *channels, Bit32u address, unsigned io_len); + channel->drives[1].controller.cylinder_no &= 0x00ff; + channel->drives[1].controller.cylinder_no |= (val2 & 0xff00); +} -static -void rd_write_handler(struct channel_t *channels, Bit32u address, - Bit32u value, unsigned io_len); +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; +} -/* - * ATAPI routines - */ -static -void rd_identify_ATAPI_drive(struct channel_t *channels, Bit8u channel); +static inline struct drive_t * get_selected_drive(struct channel_t * channel) { + return &(channel->drives[channel->drive_select]); +} -static -void rd_init_send_atapi_command(struct channel_t *channels, Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy /*= false*/); +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 -void rd_ready_to_send_atapi(struct channel_t *channels, Bit8u channel); -static -void rd_atapi_cmd_error(struct channel_t *channels, Bit8u channel, sense_t sense_key, asc_t asc); +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; + } +} -static -void rd_init_mode_sense_single(struct channel_t *channels, Bit8u channel, const void* src, int size); +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 -void rd_atapi_cmd_nop(struct channel_t *channels, Bit8u channel); -static -void rd_command_aborted(struct channel_t *channels, Bit8u channel, unsigned value); +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; +} -/* - * Interrupt handling - */ -static -void rd_raise_interrupt(struct channel_t *channels, Bit8u channel); +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 -void rd_lower_irq(struct vm_device *dev, Bit32u irq); +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; +} -/* - * Helper routines - */ -uint16 rd_read_16bit(const uint8* buf) -{ +static inline uint16_t rd_read_16bit(const uint8_t* buf) { return (buf[0] << 8) | buf[1]; } -uint32 rd_read_32bit(const uint8* buf) -{ +static inline uint32_t rd_read_32bit(const uint8_t* buf) { return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; } -//////////////////////////////////////////////////////////////////// - - -void rd_print_state(struct ramdisk_t *ramdisk, - struct vm_device *dev) -//Bit32u rd_init_harddrive(struct channel_t *channels) -{ - - 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)); - - Ramdisk_Print("sizeof(*channels) = %d\n", sizeof((*channels))); - Ramdisk_Print("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller))); - Ramdisk_Print("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom))); - Ramdisk_Print("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense))); - Ramdisk_Print("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi))); - - - Ramdisk_Print("sizeof(channles->drives[0].controller.status) = %d\n", sizeof((channels->drives[0].controller.status))); - Ramdisk_Print("sizeof(channles->drives[0].controller.sector_count) = %d\n", sizeof((channels->drives[0].controller.sector_count))); - Ramdisk_Print("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n", sizeof((channels->drives[0].controller.interrupt_reason))); - - Ramdisk_Print("sizeof(channles->drives[0].controller.cylinder_no) = %d\n", sizeof((channels->drives[0].controller.cylinder_no))); - Ramdisk_Print("sizeof(channles->drives[0].controller.byte_count) = %d\n", sizeof((channels->drives[0].controller.byte_count))); - - - Ramdisk_Print("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 - Ramdisk_Print("channels[%d].drives[%d].controller.status.busy = %d\n",channel, device, channels[channel].drives[device].controller.status.busy); - Ramdisk_Print("channels[%d].drives[%d].controller.status.drive_ready = %d\n", channel, device, channels[channel].drives[device].controller.status.drive_ready); - Ramdisk_Print("channels[%d].drives[%d].controller.status.write_fault = %d\n", channel, device, channels[channel].drives[device].controller.status.write_fault); - Ramdisk_Print("channels[%d].drives[%d].controller.status.seek_complete = %d\n", channel, device, channels[channel].drives[device].controller.status.seek_complete); - Ramdisk_Print("channels[%d].drives[%d].controller.status.drq = %d\n", channel, device, channels[channel].drives[device].controller.status.drq); - Ramdisk_Print("channels[%d].drives[%d].controller.status.corrected_data = %d\n", channel, device, channels[channel].drives[device].controller.status.corrected_data); - Ramdisk_Print("channels[%d].drives[%d].controller.status.index_pulse = %d\n", channel, device, channels[channel].drives[device].controller.status.index_pulse); - Ramdisk_Print("channels[%d].drives[%d].controller.status.index_pulse_count = %d\n", channel, device, channels[channel].drives[device].controller.status.index_pulse_count); - Ramdisk_Print("channels[%d].drives[%d].controller.status.err = %d\n", channel, device, channels[channel].drives[device].controller.status.err); +//////////////////////////////////////////////////////////////////////////// - Ramdisk_Print("channels[%d].drives[%d].controller.error_register = %d\n", channel, device, channels[channel].drives[device].controller.error_register); - Ramdisk_Print("channels[%d].drives[%d].controller.head_no = %d\n", channel, device, channels[channel].drives[device].controller.head_no); - Ramdisk_Print("channels[%d].drives[%d].controller.sector_count = %d\n", channel, device, channels[channel].drives[device].controller.sector_count); - Ramdisk_Print("channels[%d].drives[%d].controller.sector_no = %d\n", channel, device, channels[channel].drives[device].controller.sector_no); - Ramdisk_Print("channels[%d].drives[%d].controller.cylinder_no = %d\n", channel, device, channels[channel].drives[device].controller.cylinder_no); - Ramdisk_Print("channels[%d].drives[%d].controller.current_command = %02x\n", channel, device, channels[channel].drives[device].controller.current_command); - Ramdisk_Print("channels[%d].drives[%d].controller.buffer_index = %d\n", channel, device, channels[channel].drives[device].controller.buffer_index); +/* + * ATAPI routines + */ - Ramdisk_Print("channels[%d].drives[%d].controller.control.reset = %d\n", channel, device, channels[channel].drives[device].controller.control.reset); - Ramdisk_Print("channels[%d].drives[%d].controller.control.disable_irq = %d\n", channel, device, channels[channel].drives[device].controller.control.disable_irq); +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); - Ramdisk_Print("channels[%d].drives[%d].controller.reset_in_progress = %d\n", channel, device, channels[channel].drives[device].controller.reset_in_progress); - Ramdisk_Print("channels[%d].drives[%d].controller.sectors_per_block = %02x\n", channel, device, channels[channel].drives[device].controller.sectors_per_block); - Ramdisk_Print("channels[%d].drives[%d].controller.lba_mode = %d\n", channel, device, channels[channel].drives[device].controller.lba_mode); - Ramdisk_Print("channels[%d].drives[%d].controller.features = %d\n", channel, device, channels[channel].drives[device].controller.features); +/* + * 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); - Ramdisk_Print("channels[%d].drives[%d].model_no = %s\n", channel, device, channels[channel].drives[device].model_no); - Ramdisk_Print("channels[%d].drives[%d].device_type = %d\n", channel, device, channels[channel].drives[device].device_type); - Ramdisk_Print("channels[%d].drives[%d].cdrom.locked = %d\n", channel, device, channels[channel].drives[device].cdrom.locked); - Ramdisk_Print("channels[%d].drives[%d].sense.sense_key = %d\n", channel, device, channels[channel].drives[device].sense.sense_key); - Ramdisk_Print("channels[%d].drives[%d].sense.asc = %d\n", channel, device, channels[channel].drives[device].sense.asc); - Ramdisk_Print("channels[%d].drives[%d].sense.ascq = %d\n", channel, device, channels[channel].drives[device].sense.ascq); +/* + * Helper routines + */ - Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.c_d); - Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.i_o); - Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.rel); +#ifdef DEBUG_RAMDISK +static void rd_print_state(struct ramdisk_t *ramdisk, struct vm_device *dev) +static int check_bit_fields(struct controller_t * controller); +#endif +//////////////////////////////////////////////////////////////////// - Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.tag); - Ramdisk_Print("channels[%d].drives[%d].cdrom.ready = %d\n", channel, device, channels[channel].drives[device].cdrom.ready); - - }//for device - }//for channel - - return; -} -Bit32u rd_init_harddrive(struct ramdisk_t *ramdisk, - struct vm_device *dev) -{ - - uchar_t channel; - uchar_t device; +Bit32u rd_init_hardware(struct ramdisk_t *ramdisk) { + uint_t channel_num; + uint_t device; struct channel_t *channels = (struct channel_t *)(&(ramdisk->channels)); Ramdisk_Print("[rd_init_harddrive]\n"); - for (channel = 0; channel < MAX_ATA_CHANNEL; channel++) - memset((char *)(channels + channel), 0, sizeof(struct channel_t)); + for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++) { + memset((char *)(channels + channel_num), 0, sizeof(struct channel_t)); + } - for (channel = 0; channel < MAX_ATA_CHANNEL; channel++){ - - channels[channel].ioaddr1 = 0x0; - channels[channel].ioaddr2 = 0x0; - channels[channel].irq = 0; + 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(channel,device).status.busy = 0; - CONTROLLER(channel,device).status.drive_ready = 1; - CONTROLLER(channel,device).status.write_fault = 0; - CONTROLLER(channel,device).status.seek_complete = 1; - CONTROLLER(channel,device).status.drq = 0; - CONTROLLER(channel,device).status.corrected_data = 0; - CONTROLLER(channel,device).status.index_pulse = 0; - CONTROLLER(channel,device).status.index_pulse_count = 0; - CONTROLLER(channel,device).status.err = 0; - - CONTROLLER(channel,device).error_register = 0x01; // diagnostic code: no error - CONTROLLER(channel,device).head_no = 0; - CONTROLLER(channel,device).sector_count = 1; - CONTROLLER(channel,device).sector_no = 1; - CONTROLLER(channel,device).cylinder_no = 0; - CONTROLLER(channel,device).current_command = 0x00; - CONTROLLER(channel,device).buffer_index = 0; - - CONTROLLER(channel,device).control.reset = 0; - CONTROLLER(channel,device).control.disable_irq = 0; - CONTROLLER(channel,device).reset_in_progress = 0; - - CONTROLLER(channel,device).sectors_per_block = 0x80; - CONTROLLER(channel,device).lba_mode = 0; - CONTROLLER(channel,device).features = 0; + controller->features = 0; - // If not present - channels[channel].drives[device].device_type = IDE_NONE; + // If not present + drive->device_type = IDE_NONE; // Make model string - strncpy((char*)channels[channel].drives[device].model_no, - "", 40); - while(strlen((char *)channels[channel].drives[device].model_no) < 40) { - strcat ((char*)channels[channel].drives[device].model_no, " "); + strncpy((char*)(drive->model_no), "", 40); + while(strlen((char *)(drive->model_no)) < 40) { + strcat ((char*)(drive->model_no), " "); } -// Ramdisk_Print("channels[%d].drives[%d].controller.current_command = %02x\n", channel, device, channels[channel].drives[device].controller.current_command); -// Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.c_d); - -// Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.i_o); - -// Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.rel); -// Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n", channel, device, channels[channel].drives[device].controller.interrupt_reason.tag); -// Ramdisk_Print("channels[%d].drives[%d].controller.control.disable_irq = %d\n", channel, device, channels[channel].drives[device].controller.control.disable_irq); - - - if (channel == 1) { + if (channel_num == 1) { - channels[channel].ioaddr1 = 0x170; - channels[channel].ioaddr2 = 0x370; - channels[channel].irq = 15; - channels[channel].drive_select = 0; + channel->ioaddr1 = 0x170; + channel->ioaddr2 = 0x370; + channel->irq = 15; + channel->drive_select = 0; if (device == 0) { // Make model string - strncpy((char*)channels[channel].drives[device].model_no, - "Zheng's Ramdisk", 40); - while (strlen((char *)channels[channel].drives[device].model_no) < 40) { - strcat ((char*)channels[channel].drives[device].model_no, " "); + strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40); + while (strlen((char *)(drive->model_no)) < 40) { + strcat ((char*)(drive->model_no), " "); } - - Ramdisk_Print("CDROM on target %d/%d\n", channel, device); - channels[channel].drives[device].device_type = IDE_CDROM; - channels[channel].drives[device].cdrom.locked = 0; - channels[channel].drives[device].sense.sense_key = SENSE_NONE; - channels[channel].drives[device].sense.asc = 0; - channels[channel].drives[device].sense.ascq = 0; + Ramdisk_Print("CDROM on target %d/%d\n", channel, device); - - //Check bit fields - channels[channel].drives[device].controller.sector_count = 0; - channels[channel].drives[device].controller.interrupt_reason.c_d = 1; - if (channels[channel].drives[device].controller.sector_count != 0x01) { - Ramdisk_Print("interrupt reason bit field error\n"); - return INTR_REASON_BIT_ERR; - } - - channels[channel].drives[device].controller.sector_count = 0; - channels[channel].drives[device].controller.interrupt_reason.i_o = 1; - if (channels[channel].drives[device].controller.sector_count != 0x02) { - Ramdisk_Print("interrupt reason bit field error\n"); - return INTR_REASON_BIT_ERR; - } + drive->device_type = IDE_CDROM; + drive->cdrom.locked = 0; + drive->sense.sense_key = SENSE_NONE; + drive->sense.asc = 0; + drive->sense.ascq = 0; - channels[channel].drives[device].controller.sector_count = 0; - channels[channel].drives[device].controller.interrupt_reason.rel = 1; - if (channels[channel].drives[device].controller.sector_count != 0x04) { - Ramdisk_Print("interrupt reason bit field error\n"); +#ifdef RAMDISK_DEBUG + if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) { + Ramdisk_Print("interrupt reason: bit field error\n"); return INTR_REASON_BIT_ERR; } - - channels[channel].drives[device].controller.sector_count = 0; - channels[channel].drives[device].controller.interrupt_reason.tag = 3; - if (channels[channel].drives[device].controller.sector_count != 0x18) { - Ramdisk_Print("interrupt reason bit field error\n"); - return INTR_REASON_BIT_ERR; - } - +#endif - channels[channel].drives[device].controller.sector_count = 0; + controller->sector_count = 0; // allocate low level driver - channels[channel].drives[device].cdrom.cd = (struct cdrom_interface*)V3_Malloc(sizeof(struct cdrom_interface)); - Ramdisk_Print("cd = %x\n", channels[channel].drives[device].cdrom.cd); - V3_ASSERT(channels[channel].drives[device].cdrom.cd != NULL); + drive->cdrom.cd = (struct cdrom_interface*)V3_Malloc(sizeof(struct cdrom_interface)); + Ramdisk_Print("cd = %x\n", drive->cdrom.cd); + V3_ASSERT(drive->cdrom.cd != NULL); - struct cdrom_interface *cdif = channels[channel].drives[device].cdrom.cd; + struct cdrom_interface * cdif = drive->cdrom.cd; memset(cdif, 0, sizeof(struct cdrom_interface)); init_cdrom(cdif); cdif->ops.init(cdif); Ramdisk_Print("\t\tCD on ata%d-%d: '%s'\n",channel, device, ""); - if((channels[channel].drives[device].cdrom.cd->ops).insert_cdrom(cdif, NULL)) { + if((drive->cdrom.cd->ops).insert_cdrom(cdif, NULL)) { Ramdisk_Print("\t\tMedia present in CD-ROM drive\n"); - channels[channel].drives[device].cdrom.ready = 1; - channels[channel].drives[device].cdrom.capacity = channels[channel].drives[device].cdrom.cd->ops.capacity(cdif); + drive->cdrom.ready = 1; + drive->cdrom.capacity = drive->cdrom.cd->ops.capacity(cdif); } else { Ramdisk_Print("\t\tCould not locate CD-ROM, continuing with media not present\n"); - channels[channel].drives[device].cdrom.ready = 0; + drive->cdrom.ready = 0; } }//if device = 0 @@ -706,23 +456,18 @@ Bit32u rd_init_harddrive(struct ramdisk_t *ramdisk, }//for device }//for channel - ramdisk->private_data = dev; - ramdisk_state = ramdisk; - Ramdisk_Print("ramdisk_state = %x\n", ramdisk_state); - Ramdisk_Print("ramdisk = %x\n", ramdisk); - // rd_print_state(ramdisk, dev); + return 0; } -void rd_reset_harddrive(struct ramdisk_t *ramdisk, unsigned type) -{ +/* + static void rd_reset_harddrive(struct ramdisk_t *ramdisk, unsigned type) { return; -} - + } -void rd_close_harddrive(struct ramdisk_t *ramdisk) -{ +*/ +static void rd_close_harddrive(struct ramdisk_t *ramdisk) { return; } @@ -730,1141 +475,1606 @@ void rd_close_harddrive(struct ramdisk_t *ramdisk) //////////////////////////////////////////////////////////////////// -static -Bit32u rd_read_handler(struct channel_t *channels, Bit32u address, unsigned io_len) -{ - Bit8u value8; - Bit16u value16; - Bit32u value32; - unsigned drive_select; - unsigned index; - unsigned increment = 0; +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; + struct cdrom_interface *cdif = drive->cdrom.cd; - Bit8u channel = MAX_ATA_CHANNEL; - Bit32u port = 0xff; // undefined - //Ramdisk_Print("[rd_read_handler]\n"); - - for (channel=0; channel 0x03f7)) { - RD_PANIC("Error: read: unable to find ATA channel, ioport=0x%04x\n", address); - return 0; - } else { - channel = 0; - port = address - 0x03e0; - } - } - - drive_select = channels[channel].drive_select; - if (port != 0x00){ - Ramdisk_Print("[R_handler] IO read addr at %x, on drive %d/%d, curcmd = %02x\n", address, channel, drive_select, SELECTED_CONTROLLER(channel).current_command); - }else{ - + 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); - struct cdrom_interface *cdif = channels[channel].drives[drive_select].cdrom.cd; - switch (port) { + switch (controller->current_command) { + case 0xec: // IDENTIFY DEVICE + case 0xa1: + { - case 0x00: // hard disk data (16bit) 0x1f0 - switch (SELECTED_CONTROLLER(channel).current_command) { - case 0xec: // IDENTIFY DEVICE - case 0xa1: - - index = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).status.write_fault = 0; - SELECTED_CONTROLLER(channel).status.seek_complete = 1; - SELECTED_CONTROLLER(channel).status.corrected_data = 0; - SELECTED_CONTROLLER(channel).status.err = 0; + 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++; - index = SELECTED_CONTROLLER(channel).buffer_index; - value32 = SELECTED_CONTROLLER(channel).buffer[index]; - index++; - - if (io_len >= 2) { - value32 |= (SELECTED_CONTROLLER(channel).buffer[index] << 8); + if (io_len >= 2) { + value32 |= (controller->buffer[index] << 8); index++; - } - if (io_len == 4) { - value32 |= (SELECTED_CONTROLLER(channel).buffer[index] << 16); - value32 |= (SELECTED_CONTROLLER(channel).buffer[index+1] << 24); + } + + if (io_len == 4) { + value32 |= (controller->buffer[index] << 16); + value32 |= (controller->buffer[index+1] << 24); index += 2; - } - SELECTED_CONTROLLER(channel).buffer_index = index; - - if (SELECTED_CONTROLLER(channel).buffer_index >= 512) { + } - SELECTED_CONTROLLER(channel).status.drq = 0; + 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; } - GOTO_RETURN_VALUE; - - case 0xa0: //send packet cmd + + return length; + } + case 0xa0: //send packet cmd + { + uint_t index = controller->buffer_index; - index = SELECTED_CONTROLLER(channel).buffer_index; - increment = 0; - Ramdisk_Print("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n", SELECTED_DRIVE(channel).atapi.command, index, SELECTED_DRIVE(channel).cdrom.remaining_blocks); - // Load block if necessary - if (index >= 2048) { - if (index > 2048) - RD_PANIC("\t\tindex > 2048 : 0x%x\n",index); - switch (SELECTED_DRIVE(channel).atapi.command) { - case 0x28: // read (10) - case 0xa8: // read (12) - - if (!SELECTED_DRIVE(channel).cdrom.ready) { - RD_PANIC("\t\tRead with CDROM not ready\n"); - } - SELECTED_DRIVE(channel).cdrom.cd->ops.read_block(cdif, SELECTED_CONTROLLER(channel).buffer, - SELECTED_DRIVE(channel).cdrom.next_lba); - SELECTED_DRIVE(channel).cdrom.next_lba++; - SELECTED_DRIVE(channel).cdrom.remaining_blocks--; - - - if (!SELECTED_DRIVE(channel).cdrom.remaining_blocks) - Ramdisk_Print("\t\tLast READ block loaded {CDROM}\n"); - else - Ramdisk_Print("\t\tREAD block loaded (%d remaining) {CDROM}\n", - SELECTED_DRIVE(channel).cdrom.remaining_blocks); - - // one block transfered, start at beginning - index = 0; - break; - - default: // no need to load a new block - break; + + Ramdisk_Print("\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) { + RD_PANIC("\t\tindex > 2048 : 0x%x\n",index); + } + + switch (drive->atapi.command) { + case 0x28: // read (10) + case 0xa8: // read (12) + + if (!(drive->cdrom.ready)) { + RD_PANIC("\t\tRead with CDROM not ready\n"); + } + + drive->cdrom.cd->ops.read_block(cdif, controller->buffer, + drive->cdrom.next_lba); + drive->cdrom.next_lba++; + drive->cdrom.remaining_blocks--; + + + if (!(drive->cdrom.remaining_blocks)) { + Ramdisk_Print("\t\tLast READ block loaded {CDROM}\n"); + } else { + Ramdisk_Print("\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; } + } + - value32 = SELECTED_CONTROLLER(channel).buffer[index+increment]; + /* + increment = 0; + value32 = controller->buffer[index + increment]; increment++; + if (io_len >= 2) { - value32 |= (SELECTED_CONTROLLER(channel).buffer[index+increment] << 8); - increment++; + value32 |= (controller->buffer[index + increment] << 8); + increment++; } + if (io_len == 4) { - value32 |= (SELECTED_CONTROLLER(channel).buffer[index+increment] << 16); - value32 |= (SELECTED_CONTROLLER(channel).buffer[index+increment+1] << 24); - increment += 2; + value32 |= (controller->buffer[index + increment] << 16); + value32 |= (controller->buffer[index + increment + 1] << 24); + increment += 2; } - SELECTED_CONTROLLER(channel).buffer_index = index + increment; - SELECTED_CONTROLLER(channel).drq_index += increment; + + 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 (SELECTED_CONTROLLER(channel).drq_index >= (unsigned)SELECTED_DRIVE(channel).atapi.drq_bytes) { - SELECTED_CONTROLLER(channel).status.drq = 0; - SELECTED_CONTROLLER(channel).drq_index = 0; + if (drive->atapi.total_bytes_remaining > 0) { + // one or more blocks remaining (works only for single block commands) - SELECTED_DRIVE(channel).atapi.total_bytes_remaining -= SELECTED_DRIVE(channel).atapi.drq_bytes; + Ramdisk_Print("\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; - if (SELECTED_DRIVE(channel).atapi.total_bytes_remaining > 0) { - // one or more blocks remaining (works only for single block commands) - - Ramdisk_Print("\t\tPACKET drq bytes read\n"); - SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drq = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; - - // set new byte count if last block - if (SELECTED_DRIVE(channel).atapi.total_bytes_remaining < SELECTED_CONTROLLER(channel).byte_count) { - SELECTED_CONTROLLER(channel).byte_count = SELECTED_DRIVE(channel).atapi.total_bytes_remaining; - } - SELECTED_DRIVE(channel).atapi.drq_bytes = SELECTED_CONTROLLER(channel).byte_count; - - rd_raise_interrupt(channels, channel); - } else { - // all bytes read - Ramdisk_Print("\t\tPACKET all bytes read\n"); - SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drq = 0; - SELECTED_CONTROLLER(channel).status.err = 0; - - rd_raise_interrupt(channels, channel); + // 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 + Ramdisk_Print("\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); } - GOTO_RETURN_VALUE; - break; - - default: - Ramdisk_Print("\t\tread need support more command: %02x\n", SELECTED_CONTROLLER(channel).current_command); + } + return length; break; } - /////////////////////////////////////////// - - case 0x01: // hard disk error register 0x1f1 - SELECTED_CONTROLLER(channel).status.err = 0; - value8 = (!SELECTED_IS_PRESENT(channel)) ? 0 : SELECTED_CONTROLLER(channel).error_register; - goto return_value8; - break; - case 0x02: // hard disk sector count / interrupt reason 0x1f2 - value8 = (!SELECTED_IS_PRESENT(channel)) ? 0 : SELECTED_CONTROLLER(channel).sector_count; - goto return_value8; - break; - case 0x03: // sector number 0x1f3 - value8 = (!SELECTED_IS_PRESENT(channel)) ? 0 : SELECTED_CONTROLLER(channel).sector_no; - goto return_value8; - case 0x04: // 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 - value8 = (!ANY_IS_PRESENT(channel)) ? 0 : (SELECTED_CONTROLLER(channel).cylinder_no & 0x00ff); - goto return_value8; - case 0x05: // 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 - value8 = (!ANY_IS_PRESENT(channel)) ? 0 : SELECTED_CONTROLLER(channel).cylinder_no >> 8; - goto return_value8; - - case 0x06: // 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 - value8 = (1 << 7) | - ((SELECTED_CONTROLLER(channel).lba_mode>0) << 6) | - (1 << 5) | // 01b = 512 sector size - (channels[channel].drive_select << 4) | - (SELECTED_CONTROLLER(channel).head_no << 0); - goto return_value8; + default: + Ramdisk_Print("\t\tread need support more command: %02x\n", controller->current_command); break; - //CONTROLLER(channel,0).lba_mode + } + + 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); + + Ramdisk_Print("\t\twrite port 170\n"); + + switch (controller->current_command) { + case 0x30: // WRITE SECTORS + RD_PANIC("\t\tneed to implement 0x30(write sector) to port 0x170\n"); + return -1; - case 0x07: // Hard Disk Status 0x1f7 - case 0x16: // Hard Disk Alternate Status 0x3f6 - if (!ANY_IS_PRESENT(channel)) { - // (mch) Just return zero for these registers - value8 = 0; - } else { - value8 = ( - (SELECTED_CONTROLLER(channel).status.busy << 7) | - (SELECTED_CONTROLLER(channel).status.drive_ready << 6) | - (SELECTED_CONTROLLER(channel).status.write_fault << 5) | - (SELECTED_CONTROLLER(channel).status.seek_complete << 4) | - (SELECTED_CONTROLLER(channel).status.drq << 3) | - (SELECTED_CONTROLLER(channel).status.corrected_data << 2) | - (SELECTED_CONTROLLER(channel).status.index_pulse << 1) | - (SELECTED_CONTROLLER(channel).status.err) ); - SELECTED_CONTROLLER(channel).status.index_pulse_count++; - SELECTED_CONTROLLER(channel).status.index_pulse = 0; - if (SELECTED_CONTROLLER(channel).status.index_pulse_count >= INDEX_PULSE_CYCLE) { - SELECTED_CONTROLLER(channel).status.index_pulse = 1; - SELECTED_CONTROLLER(channel).status.index_pulse_count = 0; - } - } - if (port == 0x07) { - rd_lower_irq((struct vm_device *)(ramdisk_state->private_data), channels[channel].irq); - } - goto return_value8; - break; + case 0xa0: // PACKET - case 0x17: // 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 - value8 = 0xff; - goto return_value8; - break; + handle_atapi_packet_command(dev, channel, *(ushort_t *)src); + + return length; default: - RD_PANIC("hard drive: io read to address %x unsupported\n", - (unsigned) address); - + RD_PANIC("\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); + + + 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); } - Ramdisk_Print("\t\tError: hard drive: shouldnt get here!\n"); + return length; + +} + + +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 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); + + + 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; + + +typedef struct { + unsigned cylinders; + unsigned heads; + unsigned sectors; +} device_image_t; // 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; + + } return 0; +} + + +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); + + + // (mch) Even if device 1 was selected, a write to this register + // goes to device 0 (if device 1 is absent) -return_value32: - Ramdisk_Print("\t\t32-bit read from %04x = %08x {%s}\n", - (unsigned) address, value32, SELECTED_TYPE_STRING(channel)); - return value32; + 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; - return_value16: - Ramdisk_Print("\t\t16-bit read from %04x = %04x {%s}\n", - (unsigned) address, value16, SELECTED_TYPE_STRING(channel)); - return value16; + Ramdisk_Print("\t\tadpater control reg: reset controller = %d\n", + (unsigned) (controller->control.reset) ? 1 : 0); + Ramdisk_Print("\t\tadpater control reg: disable_irq(X) = %d\n", + (unsigned) (controller->control.disable_irq) ? 1 : 0); - return_value8: - Ramdisk_Print("\t\t8-bit read from %x = %02x {%s}\n", - (unsigned) address, value8, SELECTED_TYPE_STRING(channel)); - return value8; + if ((!prev_control_reset) && (controller->control.reset)) { + uint_t id = 0; + + // transition from 0 to 1 causes all drives to reset + Ramdisk_Print("\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", 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 -void rd_write_handler(struct channel_t *channels, Bit32u address, - Bit32u value, unsigned io_len) -{ +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; - // off_t logical_sector; - // off_t ret; - rd_bool prev_control_reset; - Bit32u id; - int toc_length; + if (length != 1) { + PrintError("Invalid Status port read length: %d (port=%d)\n", length, port); + return -1; + } - Bit8u channel = MAX_ATA_CHANNEL; - Bit32u port = 0xff; // undefined + 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); - //Ramdisk_Print("[rd_write_handler]\n"); - // Bit8u atapi_command; - //int alloc_length; - for (channel=0; channeldevice_type == IDE_NONE) ? 0 : controller->error_register; + + controller->status.err = 0; + + *(uchar_t *)dst = val; + return length; + break; } - else if ((address & 0xfff8) == channels[channel].ioaddr2) { - port = address - channels[channel].ioaddr2 + 0x10; + + 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; - if (channel == MAX_ATA_CHANNEL) { - if (address != 0x03f6) { - RD_PANIC("Panic: write: unable to find ATA channel, ioport=0x%04x\n", address); - } else { - channel = 0; - port = address - 0x03e0; + 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; } - Ramdisk_Print("[W_handler] IO write to %x = %02x, channel = %d\n", (unsigned) address, (unsigned) value, channel); + 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); + + *(uchar_t *)dst = val; + return length; + + 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; + } + + default: + PrintError("Invalid Port: %d\n", port); + return -1; + } +} - struct cdrom_interface *cdif = SELECTED_DRIVE(channel).cdrom.cd; - switch (port) { - case 0x00: // 0x1f0 - Ramdisk_Print("\t\twrite port 170\n"); - ////////////////////////////////////////////////////////// - switch (SELECTED_CONTROLLER(channel).current_command) { - case 0x30: // WRITE SECTORS - RD_PANIC("\t\tneed to implement 0x30(write sector) to port 0x170\n"); +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); + + + Ramdisk_Print("[W_handler] IO write to %x = %02x, channel = %d\n", + port, (unsigned) value, 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; + } + 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 + if ((value & 0xa0) != 0xa0) { + Ramdisk_Print("\t\tIO write 0x%x (%02x): not 1x1xxxxxb\n", address, (unsigned) value); + } - case 0xa0: // PACKET - if (SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) - RD_PANIC("IO write(0x%04x): buffer_index >= PACKET_SIZE", address); - SELECTED_CONTROLLER(channel).buffer[SELECTED_CONTROLLER(channel).buffer_index] = value; - SELECTED_CONTROLLER(channel).buffer[SELECTED_CONTROLLER(channel).buffer_index+1] = (value >> 8); - SELECTED_CONTROLLER(channel).buffer_index += 2; + 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); + drive->cdrom.cd->lba = (value >> 6) & 1; - /* if packet completely writtten */ - if (SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) { - // complete command received - Bit8u atapi_command = SELECTED_CONTROLLER(channel).buffer[0]; - - Ramdisk_Print("\t\tcdrom: ATAPI command 0x%x started\n", atapi_command); + + if (drive->device_type == IDE_NONE) { + channel->drive_select = (value >> 4) & 0x01; +#ifdef DEBUG_RAMDISK + PrintDebug("\t\tError: device set to %d which does not exist! channel = 0x%x\n", + channel->drive_select, channel); +#endif + controller->error_register = 0x04; // aborted + controller->status.err = 1; + } + + break; + } + default: + PrintError("\t\thard drive: io write to address %x (value = %c)\n", port, value); + return -1; + } - switch (atapi_command) { - case 0x00: // test unit ready - if (SELECTED_DRIVE(channel).cdrom.ready) { - rd_atapi_cmd_nop(channels, channel); - } else { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - rd_raise_interrupt(channels, channel); - break; - - case 0x03: { // request sense - int alloc_length = SELECTED_CONTROLLER(channel).buffer[4]; - rd_init_send_atapi_command(channels, channel, atapi_command, 18, alloc_length, false); - - // sense data - SELECTED_CONTROLLER(channel).buffer[0] = 0x70 | (1 << 7); - SELECTED_CONTROLLER(channel).buffer[1] = 0; - SELECTED_CONTROLLER(channel).buffer[2] = SELECTED_DRIVE(channel).sense.sense_key; - SELECTED_CONTROLLER(channel).buffer[3] = SELECTED_DRIVE(channel).sense.information.arr[0]; - SELECTED_CONTROLLER(channel).buffer[4] = SELECTED_DRIVE(channel).sense.information.arr[1]; - SELECTED_CONTROLLER(channel).buffer[5] = SELECTED_DRIVE(channel).sense.information.arr[2]; - SELECTED_CONTROLLER(channel).buffer[6] = SELECTED_DRIVE(channel).sense.information.arr[3]; - SELECTED_CONTROLLER(channel).buffer[7] = 17-7; - SELECTED_CONTROLLER(channel).buffer[8] = SELECTED_DRIVE(channel).sense.specific_inf.arr[0]; - SELECTED_CONTROLLER(channel).buffer[9] = SELECTED_DRIVE(channel).sense.specific_inf.arr[1]; - SELECTED_CONTROLLER(channel).buffer[10] = SELECTED_DRIVE(channel).sense.specific_inf.arr[2]; - SELECTED_CONTROLLER(channel).buffer[11] = SELECTED_DRIVE(channel).sense.specific_inf.arr[3]; - SELECTED_CONTROLLER(channel).buffer[12] = SELECTED_DRIVE(channel).sense.asc; - SELECTED_CONTROLLER(channel).buffer[13] = SELECTED_DRIVE(channel).sense.ascq; - SELECTED_CONTROLLER(channel).buffer[14] = SELECTED_DRIVE(channel).sense.fruc; - SELECTED_CONTROLLER(channel).buffer[15] = SELECTED_DRIVE(channel).sense.key_spec.arr[0]; - SELECTED_CONTROLLER(channel).buffer[16] = SELECTED_DRIVE(channel).sense.key_spec.arr[1]; - SELECTED_CONTROLLER(channel).buffer[17] = SELECTED_DRIVE(channel).sense.key_spec.arr[2]; - - rd_ready_to_send_atapi(channels, channel); - } - break; - - case 0x1b: { // start stop unit - //bx_bool Immed = (SELECTED_CONTROLLER(channel).buffer[1] >> 0) & 1; - rd_bool LoEj = (SELECTED_CONTROLLER(channel).buffer[4] >> 1) & 1; - rd_bool Start = (SELECTED_CONTROLLER(channel).buffer[4] >> 0) & 1; - - if (!LoEj && !Start) { // stop the disc - RD_ERROR("FIXME: Stop disc not implemented\n"); - rd_atapi_cmd_nop(channels, channel); - rd_raise_interrupt(channels, channel); - } else if (!LoEj && Start) { // start (spin up) the disc - - SELECTED_DRIVE(channel).cdrom.cd->ops.start_cdrom(cdif); - - RD_ERROR("FIXME: ATAPI start disc not reading TOC\n"); - rd_atapi_cmd_nop(channels, channel); - rd_raise_interrupt(channels, channel); - } else if (LoEj && !Start) { // Eject the disc - rd_atapi_cmd_nop(channels, channel); - - if (SELECTED_DRIVE(channel).cdrom.ready) { + return length; +} - SELECTED_DRIVE(channel).cdrom.cd->ops.eject_cdrom(cdif); - SELECTED_DRIVE(channel).cdrom.ready = 0; - //bx_options.atadevice[channel][SLAVE_SELECTED(channel)].Ostatus->set(EJECTED); - //bx_gui->update_drive_status_buttons(); - } - rd_raise_interrupt(channels, 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(channels, channel); - rd_raise_interrupt(channels, channel); - } + + + +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); + + Ramdisk_Print("[raise_interrupt] disable_irq = %02x\n", controller->control.disable_irq); + + if (!(controller->control.disable_irq)) { + irq = channel->irq; + + Ramdisk_Print("\t\tRaising interrupt %d {%s}\n\n", irq, SELECTED_TYPE_STRING(channel)); + + dev->vm->vm_ops.raise_irq(dev->vm, irq); + } else { + Ramdisk_Print("\t\tirq is disabled\n"); + } + + return; +} + +static void rd_lower_irq(struct vm_device *dev, Bit32u irq) // __attribute__(regparm(1)) +{ + Ramdisk_Print("[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 >= PACKET_SIZE\n"); + 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); } - break; - - case 0xbd: { // mechanism status - uint16 alloc_length = rd_read_16bit(SELECTED_CONTROLLER(channel).buffer + 8); - - if (alloc_length == 0) - RD_PANIC("Zero allocation length to MECHANISM STATUS not impl.\n"); - - rd_init_send_atapi_command(channels, channel, atapi_command, 8, alloc_length, false); - - SELECTED_CONTROLLER(channel).buffer[0] = 0; // reserved for non changers - SELECTED_CONTROLLER(channel).buffer[1] = 0; // reserved for non changers - - SELECTED_CONTROLLER(channel).buffer[2] = 0; // Current LBA (TODO!) - SELECTED_CONTROLLER(channel).buffer[3] = 0; // Current LBA (TODO!) - SELECTED_CONTROLLER(channel).buffer[4] = 0; // Current LBA (TODO!) + + rd_raise_interrupt(dev, channel); + + break; + } + case 0x03: // request sense + { + int alloc_length = controller->buffer[4]; + rd_init_send_atapi_command(dev, channel, atapi_command, 18, alloc_length, false); + + // 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 - SELECTED_CONTROLLER(channel).buffer[5] = 1; // one slot + drive->cdrom.cd->ops.start_cdrom(drive->cdrom.cd); - SELECTED_CONTROLLER(channel).buffer[6] = 0; // slot table length - SELECTED_CONTROLLER(channel).buffer[7] = 0; // slot table length + 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); - rd_ready_to_send_atapi(channels, channel); + if (drive->cdrom.ready) { + + drive->cdrom.cd->ops.eject_cdrom(drive->cdrom.cd); + + 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 0x5a: { // mode sense - uint16 alloc_length = rd_read_16bit(SELECTED_CONTROLLER(channel).buffer + 7); - - Bit8u PC = SELECTED_CONTROLLER(channel).buffer[2] >> 6; - Bit8u PageCode = SELECTED_CONTROLLER(channel).buffer[2] & 0x3f; - - switch (PC) { - case 0x0: // current values + break; + } + case 0xbd: // mechanism status + { + uint16_t alloc_length = rd_read_16bit(controller->buffer + 8); + + if (alloc_length == 0) { + RD_PANIC("Zero allocation length to MECHANISM STATUS not impl.\n"); + } + + rd_init_send_atapi_command(dev, channel, atapi_command, 8, alloc_length, false); + + 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 - rd_init_send_atapi_command(channels, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false); - - rd_init_mode_sense_single(channels, channel, &SELECTED_DRIVE(channel).cdrom.current.error_recovery, - sizeof(struct error_recovery_t)); - rd_ready_to_send_atapi(channels, channel); - break; - + { + rd_init_send_atapi_command(dev, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false); + + 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 - rd_init_send_atapi_command(channels, channel, atapi_command, 28, alloc_length, false); - rd_init_mode_sense_single(channels, channel, &SELECTED_CONTROLLER(channel).buffer[8], 28); - SELECTED_CONTROLLER(channel).buffer[8] = 0x2a; - SELECTED_CONTROLLER(channel).buffer[9] = 0x12; - SELECTED_CONTROLLER(channel).buffer[10] = 0x00; - SELECTED_CONTROLLER(channel).buffer[11] = 0x00; - // Multisession, Mode 2 Form 2, Mode 2 Form 1 - SELECTED_CONTROLLER(channel).buffer[12] = 0x70; - SELECTED_CONTROLLER(channel).buffer[13] = (3 << 5); - SELECTED_CONTROLLER(channel).buffer[14] = (unsigned char) - (1 | - (SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) | - (1 << 3) | - (1 << 5)); - SELECTED_CONTROLLER(channel).buffer[15] = 0x00; - SELECTED_CONTROLLER(channel).buffer[16] = (706 >> 8) & 0xff; - SELECTED_CONTROLLER(channel).buffer[17] = 706 & 0xff; - SELECTED_CONTROLLER(channel).buffer[18] = 0; - SELECTED_CONTROLLER(channel).buffer[19] = 2; - SELECTED_CONTROLLER(channel).buffer[20] = (512 >> 8) & 0xff; - SELECTED_CONTROLLER(channel).buffer[21] = 512 & 0xff; - SELECTED_CONTROLLER(channel).buffer[22] = (706 >> 8) & 0xff; - SELECTED_CONTROLLER(channel).buffer[23] = 706 & 0xff; - SELECTED_CONTROLLER(channel).buffer[24] = 0; - SELECTED_CONTROLLER(channel).buffer[25] = 0; - SELECTED_CONTROLLER(channel).buffer[26] = 0; - SELECTED_CONTROLLER(channel).buffer[27] = 0; - rd_ready_to_send_atapi(channels, channel); - break; - + { + rd_init_send_atapi_command(dev, channel, atapi_command, 28, alloc_length, false); + 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 - RD_ERROR("cdrom: MODE SENSE (curr), code=%x not implemented yet\n", - PageCode); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - break; - - default: - // not implemeted by this device - Ramdisk_Print("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); + { + RD_ERROR("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 + Ramdisk_Print("\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; } - break; - - case 0x1: // changeable values + 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 - RD_ERROR("cdrom: MODE SENSE (chg), code=%x not implemented yet\n", - PageCode); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); + { + 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; - - default: - // not implemeted by this device - Ramdisk_Print("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, 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 - RD_PANIC("cdrom: MODE SENSE (dflt), code=%x\n", - PageCode); - break; - + { + 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 - Ramdisk_Print("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n", - PC, PageCode); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - break; + { + // 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; } - break; - case 0x3: // saved values not implemented - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); - rd_raise_interrupt(channels, channel); - break; - + { + rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); + rd_raise_interrupt(dev, channel); + break; + } default: - RD_PANIC("Should not get here!\n"); - break; + { + RD_PANIC("Should not get here!\n"); + break; + } } + break; } - break; - - case 0x12: { // inquiry - uint8 alloc_length = SELECTED_CONTROLLER(channel).buffer[4]; - - rd_init_send_atapi_command(channels, channel, atapi_command, 36, alloc_length, false); - - SELECTED_CONTROLLER(channel).buffer[0] = 0x05; // CD-ROM - SELECTED_CONTROLLER(channel).buffer[1] = 0x80; // Removable - SELECTED_CONTROLLER(channel).buffer[2] = 0x00; // ISO, ECMA, ANSI version - SELECTED_CONTROLLER(channel).buffer[3] = 0x21; // ATAPI-2, as specified - SELECTED_CONTROLLER(channel).buffer[4] = 31; // additional length (total 36) - SELECTED_CONTROLLER(channel).buffer[5] = 0x00; // reserved - SELECTED_CONTROLLER(channel).buffer[6] = 0x00; // reserved - SELECTED_CONTROLLER(channel).buffer[7] = 0x00; // reserved - - // Vendor ID - const char* vendor_id = "VTAB "; - int i; - for (i = 0; i < 8; i++) - SELECTED_CONTROLLER(channel).buffer[8+i] = vendor_id[i]; - - // Product ID - const char* product_id = "Turbo CD-ROM "; - for (i = 0; i < 16; i++) - SELECTED_CONTROLLER(channel).buffer[16+i] = product_id[i]; - - // Product Revision level - const char* rev_level = "1.0 "; - for (i = 0; i < 4; i++) - SELECTED_CONTROLLER(channel).buffer[32+i] = rev_level[i]; - - rd_ready_to_send_atapi(channels, channel); - } - break; - - case 0x25: { // read cd-rom capacity - // no allocation length??? - rd_init_send_atapi_command(channels, channel, atapi_command, 8, 8, false); - - if (SELECTED_DRIVE(channel).cdrom.ready) { - uint32 capacity = SELECTED_DRIVE(channel).cdrom.capacity; - Ramdisk_Print("\t\tCapacity is %d sectors (%d bytes)\n", capacity, capacity * 2048); - SELECTED_CONTROLLER(channel).buffer[0] = (capacity >> 24) & 0xff; - SELECTED_CONTROLLER(channel).buffer[1] = (capacity >> 16) & 0xff; - SELECTED_CONTROLLER(channel).buffer[2] = (capacity >> 8) & 0xff; - SELECTED_CONTROLLER(channel).buffer[3] = (capacity >> 0) & 0xff; - SELECTED_CONTROLLER(channel).buffer[4] = (2048 >> 24) & 0xff; - SELECTED_CONTROLLER(channel).buffer[5] = (2048 >> 16) & 0xff; - SELECTED_CONTROLLER(channel).buffer[6] = (2048 >> 8) & 0xff; - SELECTED_CONTROLLER(channel).buffer[7] = (2048 >> 0) & 0xff; - rd_ready_to_send_atapi(channels, channel); - } else { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - } + case 0x12: // inquiry + { + uint8_t alloc_length = controller->buffer[4]; + + rd_init_send_atapi_command(dev, channel, atapi_command, 36, alloc_length, false); + + 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]; } - break; - - case 0xbe: { // read cd - if (SELECTED_DRIVE(channel).cdrom.ready) { - RD_ERROR("Read CD with CD present not implemented\n"); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - } else { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - } + + // Product ID + const char* product_id = "Turbo CD-ROM "; + for (i = 0; i < 16; i++) { + controller->buffer[16+i] = product_id[i]; } - break; - - case 0x43: { // read toc - if (SELECTED_DRIVE(channel).cdrom.ready) { - - bool msf = (SELECTED_CONTROLLER(channel).buffer[1] >> 1) & 1; - uint8 starting_track = SELECTED_CONTROLLER(channel).buffer[6]; - - uint16 alloc_length = rd_read_16bit(SELECTED_CONTROLLER(channel).buffer + 7); - - uint8 format = (SELECTED_CONTROLLER(channel).buffer[9] >> 6); - int i; - switch (format) { - case 0: - - if (!(SELECTED_DRIVE(channel).cdrom.cd->ops.read_toc(cdif, SELECTED_CONTROLLER(channel).buffer, - &toc_length, msf, starting_track))) { - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - } else { - rd_init_send_atapi_command(channels, channel, atapi_command, toc_length, alloc_length, false); - rd_ready_to_send_atapi(channels, channel); - } - break; - - case 1: - // multi session stuff. we ignore this and emulate a single session only - rd_init_send_atapi_command(channels, channel, atapi_command, 12, alloc_length, false); - - SELECTED_CONTROLLER(channel).buffer[0] = 0; - SELECTED_CONTROLLER(channel).buffer[1] = 0x0a; - SELECTED_CONTROLLER(channel).buffer[2] = 1; - SELECTED_CONTROLLER(channel).buffer[3] = 1; - for (i = 0; i < 8; i++) - SELECTED_CONTROLLER(channel).buffer[4+i] = 0; - - rd_ready_to_send_atapi(channels, channel); - break; - - case 2: - default: - RD_PANIC("(READ TOC) Format %d not supported\n", format); - break; - } - } else { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - } + + // Product Revision level + const char* rev_level = "1.0 "; + for (i = 0; i < 4; i++) { + controller->buffer[32 + i] = rev_level[i]; } - break; - - case 0x28: // read (10) - case 0xa8: // read (12) - { + + rd_ready_to_send_atapi(dev, channel); + break; + } + case 0x25: // read cd-rom capacity + { + // no allocation length??? + rd_init_send_atapi_command(dev, channel, atapi_command, 8, 8, false); - uint32 transfer_length; - if (atapi_command == 0x28) - transfer_length = rd_read_16bit(SELECTED_CONTROLLER(channel).buffer + 7); - else - transfer_length = rd_read_32bit(SELECTED_CONTROLLER(channel).buffer + 6); - - uint32 lba = rd_read_32bit(SELECTED_CONTROLLER(channel).buffer + 2); + 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 (!SELECTED_DRIVE(channel).cdrom.ready) { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - break; + if (!(drive->cdrom.cd->ops.read_toc(drive->cdrom.cd, controller->buffer, + &toc_length, msf, starting_track))) { + rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + rd_raise_interrupt(dev, channel); + } else { + rd_init_send_atapi_command(dev, channel, atapi_command, toc_length, alloc_length, false); + rd_ready_to_send_atapi(dev, channel); } + break; - if (transfer_length == 0) { - rd_atapi_cmd_nop(channels, channel); - rd_raise_interrupt(channels, channel); - Ramdisk_Print("\t\tREAD(%d) with transfer length 0, ok\n", atapi_command==0x28?10:12); - break; - } + case 1: + // multi session stuff. we ignore this and emulate a single session only + rd_init_send_atapi_command(dev, channel, atapi_command, 12, alloc_length, false); - if (lba + transfer_length > SELECTED_DRIVE(channel).cdrom.capacity) { - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - rd_raise_interrupt(channels, channel); - break; + 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; - Ramdisk_Print("\t\tcdrom: READ (%d) LBA=%d LEN=%d\n", atapi_command==0x28?10:12, lba, transfer_length); - - // handle command - rd_init_send_atapi_command(channels, channel, atapi_command, transfer_length * 2048, - transfer_length * 2048, true); - SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length; - SELECTED_DRIVE(channel).cdrom.next_lba = lba; - rd_ready_to_send_atapi(channels, channel); + 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)) { + rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + rd_raise_interrupt(dev, channel); break; - - case 0x2b: { // seek - uint32 lba = rd_read_32bit(SELECTED_CONTROLLER(channel).buffer + 2); - if (!SELECTED_DRIVE(channel).cdrom.ready) { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - break; - } - - if (lba > SELECTED_DRIVE(channel).cdrom.capacity) { - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - rd_raise_interrupt(channels, channel); - break; - } - Ramdisk_Print("\t\tcdrom: SEEK (ignored)\n"); - rd_atapi_cmd_nop(channels, channel); - rd_raise_interrupt(channels, channel); } + + if (transfer_length == 0) { + rd_atapi_cmd_nop(dev, channel); + rd_raise_interrupt(dev, channel); + Ramdisk_Print("\t\tREAD(%d) with transfer length 0, ok\n", atapi_command==0x28?10:12); break; - - case 0x1e: { // prevent/allow medium removal - if (SELECTED_DRIVE(channel).cdrom.ready) { - SELECTED_DRIVE(channel).cdrom.locked = SELECTED_CONTROLLER(channel).buffer[4] & 1; - rd_atapi_cmd_nop(channels, channel); - } else { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - rd_raise_interrupt(channels, channel); } + + if (lba + transfer_length > drive->cdrom.capacity) { + rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); + 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 data_format = get_packet_byte(channel,3); - uint8 track_number = get_packet_byte(channel,6); - uint16 alloc_length = get_packet_word(channel,7); - UNUSED(msf); - UNUSED(data_format); - UNUSED(track_number); - - if (!SELECTED_DRIVE(channel).cdrom.ready) { - rd_atapi_cmd_error(channels, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - rd_raise_interrupt(channels, channel); - } else { - SELECTED_CONTROLLER(channel).buffer[0] = 0; - SELECTED_CONTROLLER(channel).buffer[1] = 0; // audio not supported - SELECTED_CONTROLLER(channel).buffer[2] = 0; - SELECTED_CONTROLLER(channel).buffer[3] = 0; + } - int ret_len = 4; // header size + Ramdisk_Print("\t\tcdrom: READ (%d) LBA=%d LEN=%d\n", atapi_command==0x28?10:12, lba, transfer_length); - if (sub_q) { // !sub_q == header only - RD_ERROR("Read sub-channel with SubQ not implemented\n"); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - } - - rd_init_send_atapi_command(channels, channel, atapi_command, ret_len, alloc_length, false); - rd_ready_to_send_atapi(channels, channel); - } - } + // handle command + rd_init_send_atapi_command(dev, channel, atapi_command, transfer_length * 2048, + transfer_length * 2048, true); + 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; - - case 0x51: { // read disc info - // no-op to keep the Linux CD-ROM driver happy - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, 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: // ??? - RD_ERROR("ATAPI command 0x%x not implemented yet\n", - atapi_command); - rd_atapi_cmd_error(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); - break; - default: - RD_PANIC("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(channels, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - rd_raise_interrupt(channels, channel); + + if (lba > drive->cdrom.capacity) { + rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); + rd_raise_interrupt(dev, channel); break; } - } - - break; - - - default: - RD_PANIC("\t\tIO write(0x%x): current command is %02xh\n", address, - (unsigned) SELECTED_CONTROLLER(channel).current_command); - } + + PrintDebug("\t\tcdrom: SEEK (ignored)\n"); -///////////////////////////////////////////////////////// - break; - case 0x01: // hard disk write precompensation 0x1f1 - WRITE_FEATURES(channel,value); - break; + rd_atapi_cmd_nop(dev, channel); + rd_raise_interrupt(dev, channel); - case 0x02: // hard disk sector count 0x1f2 - WRITE_SECTOR_COUNT(channel,value); - break; - - case 0x03: // hard disk sector number 0x1f3 - WRITE_SECTOR_NUMBER(channel,value); - break; - - case 0x04: // hard disk cylinder low 0x1f4 - WRITE_CYLINDER_LOW(channel,value); - break; - - case 0x05: // hard disk cylinder high 0x1f5 - WRITE_CYLINDER_HIGH(channel,value); - break; - - case 0x06: // 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 - - if ( (value & 0xa0) != 0xa0 ) // 1x1xxxxx - Ramdisk_Print("\t\tIO write 0x%x (%02x): not 1x1xxxxxb\n", address, (unsigned) value); - - Bit32u drvsel = channels[channel].drive_select = (value >> 4) & 0x01; - WRITE_HEAD_NO(channel,value & 0xf); - if (SELECTED_CONTROLLER(channel).lba_mode == 0 && ((value >> 6) & 1) == 1){ - Ramdisk_Print("\t\tenabling LBA mode\n"); + 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); } - WRITE_LBA_MODE(channel,(value >> 6) & 1); - SELECTED_DRIVE(channel).cdrom.cd->lba = (value >> 6) & 1; - - - if (!SELECTED_IS_PRESENT(channel)) { - Ramdisk_Print ("\t\tError: device set to %d which does not exist! channel = %d\n",drvsel, channel); - SELECTED_CONTROLLER(channel).error_register = 0x04; // aborted - SELECTED_CONTROLLER(channel).status.err = 1; - } - - break; - - - case 0x07: // hard disk command 0x1f7 - - switch (value) { - // ATAPI commands - case 0xa1: // IDENTIFY PACKET DEVICE - if (SELECTED_IS_CD(channel)) { - SELECTED_CONTROLLER(channel).current_command = value; - SELECTED_CONTROLLER(channel).error_register = 0; - - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).status.write_fault = 0; - SELECTED_CONTROLLER(channel).status.drq = 1; - SELECTED_CONTROLLER(channel).status.err = 0; - - SELECTED_CONTROLLER(channel).status.seek_complete = 1; - SELECTED_CONTROLLER(channel).status.corrected_data = 0; - - SELECTED_CONTROLLER(channel).buffer_index = 0; - rd_raise_interrupt(channels, channel); - rd_identify_ATAPI_drive(channels, channel); - } else { - rd_command_aborted(channels, channel, 0xa1); - } - break; - - case 0xa0: // SEND PACKET (atapi) - if (SELECTED_IS_CD(channel)) { - // PACKET - if (SELECTED_CONTROLLER(channel).features & (1 << 0)) - RD_PANIC("\t\tPACKET-DMA not supported"); - if (SELECTED_CONTROLLER(channel).features & (1 << 1)) - RD_PANIC("\t\tPACKET-overlapped not supported"); - - // We're already ready! - SELECTED_CONTROLLER(channel).sector_count = 1; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.write_fault = 0; - // serv bit?? - SELECTED_CONTROLLER(channel).status.drq = 1; - SELECTED_CONTROLLER(channel).status.err = 0; - - // NOTE: no interrupt here - SELECTED_CONTROLLER(channel).current_command = value; - SELECTED_CONTROLLER(channel).buffer_index = 0; - } else { - rd_command_aborted (channels, channel, 0xa0); - } - break; - default: - Ramdisk_Print("\t\tneed translate command %2x\n", value); - break; - }//switch(value) + rd_raise_interrupt(dev, channel); - - case 0x16: // hard disk adapter control 0x3f6 - // (mch) Even if device 1 was selected, a write to this register - // goes to device 0 (if device 1 is absent) - - prev_control_reset = SELECTED_CONTROLLER(channel).control.reset; - channels[channel].drives[0].controller.control.reset = value & 0x04; - channels[channel].drives[1].controller.control.reset = value & 0x04; - // CGS: was: SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02; - channels[channel].drives[0].controller.control.disable_irq = value & 0x02; - channels[channel].drives[1].controller.control.disable_irq = value & 0x02; - - Ramdisk_Print("\t\tadpater control reg: reset controller = %d\n", - (unsigned) (SELECTED_CONTROLLER(channel).control.reset) ? 1 : 0); - Ramdisk_Print("\t\tadpater control reg: disable_irq(X) = %d\n", - (unsigned) (SELECTED_CONTROLLER(channel).control.disable_irq) ? 1 : 0); - - if (!prev_control_reset && SELECTED_CONTROLLER(channel).control.reset) { - // transition from 0 to 1 causes all drives to reset - Ramdisk_Print("\t\thard drive: RESET\n"); - - // (mch) Set BSY, drive not ready - for (id = 0; id < 2; id++) { - CONTROLLER(channel,id).status.busy = 1; - CONTROLLER(channel,id).status.drive_ready = 0; - CONTROLLER(channel,id).reset_in_progress = 1; - - CONTROLLER(channel,id).status.write_fault = 0; - CONTROLLER(channel,id).status.seek_complete = 1; - CONTROLLER(channel,id).status.drq = 0; - CONTROLLER(channel,id).status.corrected_data = 0; - CONTROLLER(channel,id).status.err = 0; - - CONTROLLER(channel,id).error_register = 0x01; // diagnostic code: no error - - CONTROLLER(channel,id).current_command = 0x00; - CONTROLLER(channel,id).buffer_index = 0; - - CONTROLLER(channel,id).sectors_per_block = 0x80; - CONTROLLER(channel,id).lba_mode = 0; - - CONTROLLER(channel,id).control.disable_irq = 0; - rd_lower_irq((struct vm_device *)(ramdisk_state->private_data), channels[channel].irq); + break; } - } else if (SELECTED_CONTROLLER(channel).reset_in_progress && - !SELECTED_CONTROLLER(channel).control.reset) { - // Clear BSY and DRDY - Ramdisk_Print("\t\tReset complete {%s}\n", SELECTED_TYPE_STRING(channel)); - for (id = 0; id < 2; id++) { - CONTROLLER(channel,id).status.busy = 0; - CONTROLLER(channel,id).status.drive_ready = 1; - CONTROLLER(channel,id).reset_in_progress = 0; + 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); - // Device signature - if (DRIVE_IS_HD(channel,id)) { - Ramdisk_Print("\t\tdrive %d/%d is harddrive\n", channel, id); - CONTROLLER(channel,id).head_no = 0; - CONTROLLER(channel,id).sector_count = 1; - CONTROLLER(channel,id).sector_no = 1; - CONTROLLER(channel,id).cylinder_no = 0; + + /* + 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(channel,id).head_no = 0; - CONTROLLER(channel,id).sector_count = 1; - CONTROLLER(channel,id).sector_no = 1; - CONTROLLER(channel,id).cylinder_no = 0xeb14; + 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); + } + + rd_init_send_atapi_command(dev, channel, atapi_command, ret_len, alloc_length, false); + 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; } - Ramdisk_Print("\t\ts[0].controller.control.disable_irq = %02x\n", (channels[channel].drives[0]).controller.control.disable_irq); - Ramdisk_Print("\t\ts[1].controller.control.disable_irq = %02x\n", (channels[channel].drives[1]).controller.control.disable_irq); - break; + } + return 0; +} + + + + +void 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. + + Ramdisk_Print("[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)) { + + Ramdisk_Print("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n", + controller->byte_count, + command, + controller->byte_count - 1); - default: - RD_PANIC("\t\thard drive: io write to address %x = %02x\n", - (unsigned) address, (unsigned) value); + controller->byte_count -= 1; + } + + if (controller->byte_count == 0) { + RD_PANIC("\t\tATAPI command with zero byte count\n"); + } + + if (alloc_length < 0) { + RD_PANIC("\t\tAllocation length < 0\n"); + } + + 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; - return; + // if (lazy) { + // // bias drq_bytes and total_bytes_remaining + // SELECTED_DRIVE(channel).atapi.drq_bytes += 2048; + // SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048; + // } } -static -void rd_identify_ATAPI_drive(struct channel_t *channels, Bit8u channel) + + void rd_ready_to_send_atapi(struct vm_device * dev, struct channel_t * channel) { + Ramdisk_Print("[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) { - unsigned i; + struct drive_t * drive = &(channel->drives[channel->drive_select]); + struct controller_t * controller = &(drive->controller); + + Ramdisk_Print("[rd_atapi_cmd_error]\n"); + Ramdisk_Print("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n", channel, sense_key, asc); + + 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); + + Ramdisk_Print("[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 "; - SELECTED_DRIVE(channel).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++) - SELECTED_DRIVE(channel).id_drive[i] = 0; + 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++) { - SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | - serial_number[i*2 + 1]; + drive->id_drive[10 + i] = ((serial_number[i * 2] << 8) | + (serial_number[(i * 2) + 1])); } - for (i = 20; i <= 22; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; - + for (i = 20; i <= 22; i++) { + drive->id_drive[i] = 0; + } for (i = 0; i < strlen(firmware)/2; i++) { - SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | - firmware[i*2 + 1]; + drive->id_drive[23 + i] = ((firmware[i * 2] << 8) | + (firmware[(i * 2) + 1])); } - V3_ASSERT((23+i) == 27); + V3_ASSERT((23 + i) == 27); - for (i = 0; i < strlen((char *) SELECTED_MODEL(channel))/2; i++) { - SELECTED_DRIVE(channel).id_drive[27+i] = (SELECTED_MODEL(channel)[i*2] << 8) | - SELECTED_MODEL(channel)[i*2 + 1]; + 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); + V3_ASSERT((27 + i) == 47); - SELECTED_DRIVE(channel).id_drive[47] = 0; - SELECTED_DRIVE(channel).id_drive[48] = 1; // 32 bits access + drive->id_drive[47] = 0; + drive->id_drive[48] = 1; // 32 bits access - SELECTED_DRIVE(channel).id_drive[49] = (1 << 9); // LBA supported + drive->id_drive[49] = (1 << 9); // LBA supported - SELECTED_DRIVE(channel).id_drive[50] = 0; - SELECTED_DRIVE(channel).id_drive[51] = 0; - SELECTED_DRIVE(channel).id_drive[52] = 0; + drive->id_drive[50] = 0; + drive->id_drive[51] = 0; + drive->id_drive[52] = 0; - SELECTED_DRIVE(channel).id_drive[53] = 3; // words 64-70, 54-58 valid + drive->id_drive[53] = 3; // words 64-70, 54-58 valid - for (i = 54; i <= 62; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; + for (i = 54; i <= 62; i++) { + drive->id_drive[i] = 0; + } // copied from CFA540A - SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) - SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO - SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; - SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; - SELECTED_DRIVE(channel).id_drive[67] = 0x012c; - SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; - - SELECTED_DRIVE(channel).id_drive[69] = 0; - SELECTED_DRIVE(channel).id_drive[70] = 0; - SELECTED_DRIVE(channel).id_drive[71] = 30; // faked - SELECTED_DRIVE(channel).id_drive[72] = 30; // faked - SELECTED_DRIVE(channel).id_drive[73] = 0; - SELECTED_DRIVE(channel).id_drive[74] = 0; - - SELECTED_DRIVE(channel).id_drive[75] = 0; - - for (i = 76; i <= 79; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; - - SELECTED_DRIVE(channel).id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 - SELECTED_DRIVE(channel).id_drive[81] = 0; - SELECTED_DRIVE(channel).id_drive[82] = 0; - SELECTED_DRIVE(channel).id_drive[83] = 0; - SELECTED_DRIVE(channel).id_drive[84] = 0; - SELECTED_DRIVE(channel).id_drive[85] = 0; - SELECTED_DRIVE(channel).id_drive[86] = 0; - SELECTED_DRIVE(channel).id_drive[87] = 0; - SELECTED_DRIVE(channel).id_drive[88] = 0; - - for (i = 89; i <= 126; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; - - SELECTED_DRIVE(channel).id_drive[127] = 0; - SELECTED_DRIVE(channel).id_drive[128] = 0; - - for (i = 129; i <= 159; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; - - for (i = 160; i <= 255; i++) - SELECTED_DRIVE(channel).id_drive[i] = 0; + 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 = SELECTED_DRIVE(channel).id_drive[i]; - SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff; - SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8; + temp16 = drive->id_drive[i]; + controller->buffer[i * 2] = temp16 & 0x00ff; + controller->buffer[i * 2 + 1] = temp16 >> 8; } return; @@ -1872,112 +2082,322 @@ void rd_identify_ATAPI_drive(struct channel_t *channels, Bit8u channel) + + + + static -void rd_raise_interrupt(struct channel_t *channels, Bit8u channel) +void rd_init_mode_sense_single(struct vm_device * dev, + struct channel_t * channel, const void* src, int size) { - Bit32u irq; - struct vm_device *dev; + struct drive_t * drive = &(channel->drives[channel->drive_select]); + struct controller_t * controller = &(drive->controller); - Ramdisk_Print("[raise_interrupt] disable_irq = %02x\n", SELECTED_CONTROLLER(channel).control.disable_irq); + Ramdisk_Print("[rd_init_mode_sense_single]\n"); - if (!SELECTED_CONTROLLER(channel).control.disable_irq) { - Ramdisk_Print("\t\traising interrupt\n"); - } else { - Ramdisk_Print("\t\tNot raising interrupt\n"); - } - if (!SELECTED_CONTROLLER(channel).control.disable_irq) { - irq = channels[channel].irq; - Ramdisk_Print("\t\tRaising interrupt %d {%s}\n\n", irq, SELECTED_TYPE_STRING(channel)); - // DEV_pic_raise_irq(irq); - dev = (struct vm_device*) ramdisk_state->private_data; - Ramdisk_Print("\t\tdev = %x\n", dev); - dev->vm->vm_ops.raise_irq(dev->vm, irq); - } else { - Ramdisk_Print("\t\tirq is disabled\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 - return; + // Data + memcpy(controller->buffer + 8, src, size); } -static -void rd_lower_irq(struct vm_device *dev, Bit32u irq)// __attribute__(regparm(1)) -{ - Ramdisk_Print("[lower_irq] irq = %d\n", irq); - dev->vm->vm_ops.lower_irq(dev->vm, irq); + + +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); + + Ramdisk_Print("[rd_command_aborted]\n"); + Ramdisk_Print("\t\taborting on command 0x%02x {%s}\n", value, SELECTED_TYPE_STRING(channel)); + + 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); } -/* - * Public Routines - */ -static -int ramdisk_read_port(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev) -{ - uint_t i; - //Ramdisk_Print("[ramdisk_read_port] port = %x, length = %d\n", port, length); - switch (length) { - case 1: - ((uchar_t*)src)[0] = rd_read_handler(ramdisk_state->channels, port, length); - break; - case 2: - ((ushort_t*)src)[0] = rd_read_handler(ramdisk_state->channels, port, length); - break; - case 4: - ((uint_t*)src)[0] = rd_read_handler(ramdisk_state->channels, port, length); - break; - default: - for (i = 0; i < length; i++) { - ((uchar_t*)src)[i] = rd_read_handler(ramdisk_state->channels, port, 1); - } - }//switch length +static int ramdisk_init_device(struct vm_device *dev) { + struct ramdisk_t *ramdisk_state = (struct ramdisk_t *)dev->private_data; + + rd_init_hardware(ramdisk_state); + + + 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; - return length; } -static -int ramdisk_write_port(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev) +static int ramdisk_deinit_device(struct vm_device *dev) { + struct ramdisk_t *ramdisk_state = (struct ramdisk_t *)(dev->private_data); + rd_close_harddrive(ramdisk_state); + 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() { - //Ramdisk_Print("[ramdisk_write_port] port = %x, length = %d\n", port, length); - /* - uint_t i; - for (i = 0; i < length; i++) - Ramdisk_Print("\t\tsrc[%d] = 0x%02x\n", i, ((uchar_t*)src)[i]); - */ + struct ramdisk_t *ramdisk; + ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t)); + V3_ASSERT(ramdisk != NULL); + + Ramdisk_Print("[create_ramdisk]\n"); - switch(length) { - case 1: - rd_write_handler(ramdisk_state->channels, port, *((uchar_t *)src), length); - break; - case 2: - rd_write_handler(ramdisk_state->channels, port, *((ushort_t *)src), length); - break; - case 4: - rd_write_handler(ramdisk_state->channels, port, *((uint_t *)src), length); - break; - default: - rd_write_handler(ramdisk_state->channels, port, *((uchar_t *)src), length); - break; + struct vm_device *device = create_device("RAMDISK", &dev_ops, ramdisk); + + return device; +} + + + + +#ifdef RAMDISK_DEBUG +static void rd_print_state(struct ramdisk_t * ramdisk, struct vm_device *dev) { + 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)); } - return length; + Ramdisk_Print("sizeof(*channels) = %d\n", sizeof(*channels)); + Ramdisk_Print("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller))); + Ramdisk_Print("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom))); + Ramdisk_Print("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense))); + Ramdisk_Print("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi))); + + + Ramdisk_Print("sizeof(channles->drives[0].controller.status) = %d\n", + sizeof((channels->drives[0].controller.status))); + Ramdisk_Print("sizeof(channles->drives[0].controller.sector_count) = %d\n", + sizeof((channels->drives[0].controller.sector_count))); + Ramdisk_Print("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n", + sizeof((channels->drives[0].controller.interrupt_reason))); + + Ramdisk_Print("sizeof(channles->drives[0].controller.cylinder_no) = %d\n", + sizeof((channels->drives[0].controller.cylinder_no))); + Ramdisk_Print("sizeof(channles->drives[0].controller.byte_count) = %d\n", + sizeof((channels->drives[0].controller.byte_count))); + + + Ramdisk_Print("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 + Ramdisk_Print("channels[%d].drives[%d].controller.status.busy = %d\n", + channel, device, + channels[channel].drives[device].controller.status.busy); + Ramdisk_Print("channels[%d].drives[%d].controller.status.drive_ready = %d\n", + channel, device, + channels[channel].drives[device].controller.status.drive_ready); + Ramdisk_Print("channels[%d].drives[%d].controller.status.write_fault = %d\n", + channel, device, + channels[channel].drives[device].controller.status.write_fault); + Ramdisk_Print("channels[%d].drives[%d].controller.status.seek_complete = %d\n", + channel, device, + channels[channel].drives[device].controller.status.seek_complete); + Ramdisk_Print("channels[%d].drives[%d].controller.status.drq = %d\n", + channel, device, + channels[channel].drives[device].controller.status.drq); + Ramdisk_Print("channels[%d].drives[%d].controller.status.corrected_data = %d\n", + channel, device, + channels[channel].drives[device].controller.status.corrected_data); + Ramdisk_Print("channels[%d].drives[%d].controller.status.index_pulse = %d\n", + channel, device, + channels[channel].drives[device].controller.status.index_pulse); + Ramdisk_Print("channels[%d].drives[%d].controller.status.index_pulse_count = %d\n", + channel, device, + channels[channel].drives[device].controller.status.index_pulse_count); + Ramdisk_Print("channels[%d].drives[%d].controller.status.err = %d\n", + channel, device, + channels[channel].drives[device].controller.status.err); + + + Ramdisk_Print("channels[%d].drives[%d].controller.error_register = %d\n", + channel, device, + channels[channel].drives[device].controller.error_register); + Ramdisk_Print("channels[%d].drives[%d].controller.head_no = %d\n", + channel, device, + channels[channel].drives[device].controller.head_no); + Ramdisk_Print("channels[%d].drives[%d].controller.sector_count = %d\n", + channel, device, + channels[channel].drives[device].controller.sector_count); + Ramdisk_Print("channels[%d].drives[%d].controller.sector_no = %d\n", + channel, device, + channels[channel].drives[device].controller.sector_no); + Ramdisk_Print("channels[%d].drives[%d].controller.cylinder_no = %d\n", + channel, device, + channels[channel].drives[device].controller.cylinder_no); + Ramdisk_Print("channels[%d].drives[%d].controller.current_command = %02x\n", + channel, device, + channels[channel].drives[device].controller.current_command); + Ramdisk_Print("channels[%d].drives[%d].controller.buffer_index = %d\n", + channel, device, + channels[channel].drives[device].controller.buffer_index); + + + Ramdisk_Print("channels[%d].drives[%d].controller.control.reset = %d\n", + channel, device, + channels[channel].drives[device].controller.control.reset); + Ramdisk_Print("channels[%d].drives[%d].controller.control.disable_irq = %d\n", + channel, device, + channels[channel].drives[device].controller.control.disable_irq); + + + Ramdisk_Print("channels[%d].drives[%d].controller.reset_in_progress = %d\n", + channel, device, + channels[channel].drives[device].controller.reset_in_progress); + Ramdisk_Print("channels[%d].drives[%d].controller.sectors_per_block = %02x\n", + channel, device, + channels[channel].drives[device].controller.sectors_per_block); + Ramdisk_Print("channels[%d].drives[%d].controller.lba_mode = %d\n", + channel, device, + channels[channel].drives[device].controller.lba_mode); + Ramdisk_Print("channels[%d].drives[%d].controller.features = %d\n", + channel, device, + channels[channel].drives[device].controller.features); + + + Ramdisk_Print("channels[%d].drives[%d].model_no = %s\n", + channel, device, + channels[channel].drives[device].model_no); + Ramdisk_Print("channels[%d].drives[%d].device_type = %d\n", + channel, device, + channels[channel].drives[device].device_type); + Ramdisk_Print("channels[%d].drives[%d].cdrom.locked = %d\n", + channel, device, + channels[channel].drives[device].cdrom.locked); + Ramdisk_Print("channels[%d].drives[%d].sense.sense_key = %d\n", + channel, device, + channels[channel].drives[device].sense.sense_key); + Ramdisk_Print("channels[%d].drives[%d].sense.asc = %d\n", + channel, device, + channels[channel].drives[device].sense.asc); + Ramdisk_Print("channels[%d].drives[%d].sense.ascq = %d\n", + channel, device, + channels[channel].drives[device].sense.ascq); + + + + Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n", + channel, device, + channels[channel].drives[device].controller.interrupt_reason.c_d); + + Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n", + channel, device, + channels[channel].drives[device].controller.interrupt_reason.i_o); + + Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n", + channel, device, + channels[channel].drives[device].controller.interrupt_reason.rel); + + Ramdisk_Print("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n", + channel, device, + channels[channel].drives[device].controller.interrupt_reason.tag); + + Ramdisk_Print("channels[%d].drives[%d].cdrom.ready = %d\n", + channel, device, + channels[channel].drives[device].cdrom.ready); + + } //for device + } //for channel + + return; } -static void trace_info(ushort_t port, void *src, uint_t length) -{ + +static void trace_info(ushort_t port, void *src, uint_t length) { + switch(port){ case 0x3e8: if (length == 1 && *((uchar_t*) src) == ATA_DETECT) - Ramdisk_Print("ata_dectect()\n"); + Ramdisk_Print("ata_detect()\n"); break; case 0x3e9: @@ -2083,355 +2503,33 @@ static void trace_info(ushort_t port, void *src, uint_t length) } -int ramdisk_read_port_ignore(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev) -{ - // Ramdisk_Print("[ramdisk_read_port_ignore] port = %x, length = %d\n", port, length); - return length; -} - -int ramdisk_write_port_ignore(ushort_t port, - void *src, - uint_t length, - struct vm_device *dev) -{ - - // Ramdisk_Print("[ramdisk_write_port_ignore] port = %x, length = %d\n", port, length); - - trace_info(port, src, length); - return length; -} -////////////////////////////////////////////////////////////////////////// - -/* - * ATAPI subroutines - */ - -static -void rd_init_send_atapi_command(struct channel_t *channels, Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy) -{ - // SELECTED_CONTROLLER(channel).byte_count is a union of SELECTED_CONTROLLER(channel).cylinder_no; - // lazy is used to force a data read in the buffer at the next read. - - Ramdisk_Print("[rd_init_send_atapi_cmd]\n"); - if (SELECTED_CONTROLLER(channel).byte_count == 0xffff) - SELECTED_CONTROLLER(channel).byte_count = 0xfffe; - - if ((SELECTED_CONTROLLER(channel).byte_count & 1) - && !(alloc_length <= SELECTED_CONTROLLER(channel).byte_count)) { - Ramdisk_Print("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n", - SELECTED_CONTROLLER(channel).byte_count, command, SELECTED_CONTROLLER(channel).byte_count - 1); - SELECTED_CONTROLLER(channel).byte_count -= 1; +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; } - if (SELECTED_CONTROLLER(channel).byte_count == 0) - RD_PANIC("\t\tATAPI command with zero byte count\n"); - - if (alloc_length < 0) - RD_PANIC("\t\tAllocation length < 0\n"); - if (alloc_length == 0) - alloc_length = SELECTED_CONTROLLER(channel).byte_count; - - SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drq = 1; - SELECTED_CONTROLLER(channel).status.err = 0; - - // no bytes transfered yet - if (lazy) - SELECTED_CONTROLLER(channel).buffer_index = 2048; - else - SELECTED_CONTROLLER(channel).buffer_index = 0; - SELECTED_CONTROLLER(channel).drq_index = 0; - - if (SELECTED_CONTROLLER(channel).byte_count > req_length) - SELECTED_CONTROLLER(channel).byte_count = req_length; - - if (SELECTED_CONTROLLER(channel).byte_count > alloc_length) - SELECTED_CONTROLLER(channel).byte_count = alloc_length; - - SELECTED_DRIVE(channel).atapi.command = command; - SELECTED_DRIVE(channel).atapi.drq_bytes = SELECTED_CONTROLLER(channel).byte_count; - SELECTED_DRIVE(channel).atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; + controller->sector_count = 0; + controller->interrupt_reason.i_o = 1; + if (controller->sector_count != 0x02) { + return INTR_REASON_BIT_ERR; + } - // if (lazy) { - // // bias drq_bytes and total_bytes_remaining - // SELECTED_DRIVE(channel).atapi.drq_bytes += 2048; - // SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048; - // } -} - - -static -void rd_atapi_cmd_error(struct channel_t *channels, Bit8u channel, sense_t sense_key, asc_t asc) -{ - Ramdisk_Print("[rd_atapi_cmd_error]\n"); - Ramdisk_Print("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n", channel, sense_key, asc); - - SELECTED_CONTROLLER(channel).error_register = sense_key << 4; - SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).status.write_fault = 0; - SELECTED_CONTROLLER(channel).status.drq = 0; - SELECTED_CONTROLLER(channel).status.err = 1; + controller->sector_count = 0; + controller->interrupt_reason.rel = 1; + if (controller->sector_count != 0x04) { + return INTR_REASON_BIT_ERR; + } - SELECTED_DRIVE(channel).sense.sense_key = sense_key; - SELECTED_DRIVE(channel).sense.asc = asc; - SELECTED_DRIVE(channel).sense.ascq = 0; -} - - -static -void rd_atapi_cmd_nop(struct channel_t *channels, Bit8u channel) -{ - Ramdisk_Print("[rd_atapi_cmd_nop]\n"); - SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).status.drq = 0; - SELECTED_CONTROLLER(channel).status.err = 0; -} - - -static -void rd_init_mode_sense_single(struct channel_t *channels, - Bit8u channel, const void* src, int size) -{ - Ramdisk_Print("[rd_init_mode_sense_single]\n"); - // Header - SELECTED_CONTROLLER(channel).buffer[0] = (size+6) >> 8; - SELECTED_CONTROLLER(channel).buffer[1] = (size+6) & 0xff; - SELECTED_CONTROLLER(channel).buffer[2] = 0x70; // no media present - SELECTED_CONTROLLER(channel).buffer[3] = 0; // reserved - SELECTED_CONTROLLER(channel).buffer[4] = 0; // reserved - SELECTED_CONTROLLER(channel).buffer[5] = 0; // reserved - SELECTED_CONTROLLER(channel).buffer[6] = 0; // reserved - SELECTED_CONTROLLER(channel).buffer[7] = 0; // reserved + controller->sector_count = 0; + controller->interrupt_reason.tag = 3; + if (controller->sector_count != 0x18) { + return INTR_REASON_BIT_ERR; + } - // Data - memcpy(SELECTED_CONTROLLER(channel).buffer + 8, src, size); -} - - -static -void rd_ready_to_send_atapi(struct channel_t *channels, Bit8u channel) -{ - Ramdisk_Print("[rd_ready_to_send_atapi]\n"); - rd_raise_interrupt(ramdisk_state->channels, channel); -} - - -static -void rd_command_aborted(struct channel_t *channels, - Bit8u channel, unsigned value) -{ - Ramdisk_Print("[rd_command_aborted]\n"); - Ramdisk_Print("\t\taborting on command 0x%02x {%s}\n", value, SELECTED_TYPE_STRING(channel)); - SELECTED_CONTROLLER(channel).current_command = 0; - SELECTED_CONTROLLER(channel).status.busy = 0; - SELECTED_CONTROLLER(channel).status.drive_ready = 1; - SELECTED_CONTROLLER(channel).status.err = 1; - SELECTED_CONTROLLER(channel).error_register = 0x04; // command ABORTED - SELECTED_CONTROLLER(channel).status.drq = 0; - SELECTED_CONTROLLER(channel).status.seek_complete = 0; - SELECTED_CONTROLLER(channel).status.corrected_data = 0; - SELECTED_CONTROLLER(channel).buffer_index = 0; - rd_raise_interrupt(ramdisk_state->channels, channel); -} - - -static int ramdisk_init_device(struct vm_device *dev) -{ - struct ramdisk_t *ramdisk_state = (struct ramdisk_t *)dev->private_data; - - ramdisk_state->cops.init(ramdisk_state, dev); - - //hook ports IDE 0x170-0x177, 0x376 & 0x377 - dev_hook_io(dev, 0x170, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x171, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x172, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x173, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x174, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x175, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x176, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x177, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x376, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - dev_hook_io(dev, 0x377, - (ramdisk_state->eops.read_port), - (ramdisk_state->eops.write_port)); - - //Debug ports: 0x3e8-0x3ef & 0x2e8-0x2ef - -#ifdef DEBUG_RAMDISK - - dev_hook_io(dev, 0x3e8, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3e9, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3ea, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3eb, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3ec, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3ed, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3ee, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x3ef, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2e8, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2e9, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2ea, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2eb, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2ec, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2ed, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2ee, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - - dev_hook_io(dev, 0x2ef, - (ramdisk_state->eops.read_port_ignore), - (ramdisk_state->eops.write_port_ignore)); - -#endif - -} - - -static int ramdisk_deinit_device(struct vm_device *dev) -{ - struct ramdisk_t *ramdisk_state = (struct ramdisk_t *)(dev->private_data); - ramdisk_state->cops.close(ramdisk_state); - return 0; } - -static struct vm_device_ops dev_ops = { - .init = ramdisk_init_device, - .deinit = ramdisk_deinit_device, - .reset = NULL, - .start = NULL, - .stop = NULL, -}; - - - -/* - * Success: return 0; - * Failure: return integer greater than 0 - */ - -/* -struct ramdisk_t * create_ramdisk() -{ - struct ramdisk_t *ramdisk; - ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t)); - V3_ASSERT(ramdisk != NULL); - - ramdisk->cops.init = &rd_init_harddrive; - ramdisk->cops.close = &rd_close_harddrive; - ramdisk->cops.reset = &rd_reset_harddrive; - - ramdisk->eops.read_port = &ramdisk_read_port; - ramdisk->eops.write_port = &ramdisk_write_port; - ramdisk->eops.read_port_ignore = &ramdisk_read_port_ignore; - ramdisk->eops.write_port_ignore = &ramdisk_write_port_ignore; - - return ramdisk; -} - -*/ - - -struct vm_device *create_ramdisk() -{ - - struct ramdisk_t *ramdisk; - ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t)); - V3_ASSERT(ramdisk != NULL); - - Ramdisk_Print("[create_ramdisk]\n"); - ramdisk->cops.init = &rd_init_harddrive; - ramdisk->cops.close = &rd_close_harddrive; - ramdisk->cops.reset = &rd_reset_harddrive; - - ramdisk->eops.read_port = &ramdisk_read_port; - ramdisk->eops.write_port = &ramdisk_write_port; - ramdisk->eops.read_port_ignore = &ramdisk_read_port_ignore; - ramdisk->eops.write_port_ignore = &ramdisk_write_port_ignore; - - struct vm_device *device = create_device("RAMDISK", &dev_ops, ramdisk); - - return device; -} +#endif diff --git a/palacios/src/geekos/mem.c b/palacios/src/geekos/mem.c index 7bfb8aa..69acef5 100644 --- a/palacios/src/geekos/mem.c +++ b/palacios/src/geekos/mem.c @@ -34,10 +34,9 @@ */ struct Page* g_pageList; -#ifdef RAMDISK_BOOT ulong_t g_ramdiskImage; ulong_t s_ramdiskSize; -#endif + /* * Number of pages currently available on the freelist. @@ -142,13 +141,12 @@ void Init_Mem(struct Boot_Info* bootInfo) ulong_t heapEnd; ulong_t vmmMemEnd; - /*Zheng 08/03/2008*/ -#ifdef RAMDISK_BOOT + g_ramdiskImage = bootInfo->ramdisk_image; s_ramdiskSize = bootInfo->ramdisk_size; ulong_t initrdAddr; ulong_t initrdEnd; -#endif + KASSERT(bootInfo->memSizeKB > 0); @@ -204,7 +202,6 @@ void Init_Mem(struct Boot_Info* bootInfo) /* ** */ vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE); -#ifdef RAMDISK_BOOT /* * Zheng 08/03/2008 * copy the ramdisk to this area @@ -216,23 +213,23 @@ void Init_Mem(struct Boot_Info* bootInfo) memcpy((ulong_t *)initrdAddr, (ulong_t *)g_ramdiskImage, s_ramdiskSize); PrintBoth(" done\n"); PrintBoth("mem.c(%d) Set 0 to unused bytes in the last ramdisk page from %x to %x", __LINE__, initrdAddr+s_ramdiskSize, initrdEnd); - memset((ulong_t *)initrdAddr+s_ramdiskSize, 0, initrdEnd-(initrdAddr+s_ramdiskSize)); + memset((ulong_t *)initrdAddr + s_ramdiskSize, 0, initrdEnd - (initrdAddr + s_ramdiskSize)); PrintBoth(" done\n"); - /* - * Zheng 08/03/2008 - */ - vm_range_start = initrdEnd; - vm_range_end = endOfMem; -#else + + /* * the disgusting way to get at the memory assigned to a VM */ - vm_range_start = vmmMemEnd; - vm_range_end = endOfMem; - -#endif + //vm_range_start = vmmMemEnd; + //vm_range_end = endOfMem; + /* + * Zheng 08/03/2008 + */ + vm_range_start = initrdEnd; + vm_range_end = endOfMem; + Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED); // BIOS area Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED); // Intial kernel thread obj + stack diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 1dc5996..17ca9e4 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -177,12 +177,15 @@ int config_guest(struct guest_info * info, void * config_ptr) { struct vm_device * generic = NULL; //Zheng 09/29/2008 + if (use_ramdisk) { + PrintDebug("Creating Ramdisk\n"); ramdisk = create_ramdisk(); } if (use_generic) { + PrintDebug("Creating Generic Device\n"); generic = create_generic(); // Make the DMA controller invisible