#include <devices/ide.h>
+#ifndef TRACE_RAMDISK
+#undef PrintTrace
+#define PrintTrace(fmt, args...)
+#endif
+
+
#ifndef DEBUG_RAMDISK
#undef PrintDebug
-#define PrintDebug(_f, _a...)
+#define PrintDebug(fmt, args...)
#endif
-
+
+
+
+
/*
* Data type definitions
#define SEC_ADDR_REG_PORT 0x377
-
-
-
#define PACKET_SIZE 12
-// FLAT MODE
-// Open a image. Returns non-negative if successful.
-//int open (const char* pathname);
-
-// Open an image with specific flags. Returns non-negative if successful.
-int rd_open (const char* pathname, int flags);
-
-// Close the image.
-void rd_close ();
-
-// Position ourselves. Return the resulting offset from the
-// beginning of the file.
-off_t rd_lseek (off_t offset, int whence);
-
-// Read count bytes to the buffer buf. Return the number of
-// bytes read (count).
-ssize_t rd_read (void* buf, size_t count);
-
-// Write count bytes from buf. Return the number of bytes
-// written (count).
-ssize_t rd_write (const void* buf, size_t count);
-
-
-
-
-
-/*
- * Debug facilities
- */
-
-#define ATA_DETECT 0xf0 //0X3E8
-#define ATA_RESET 0xf1 //0X3E9
-#define ATA_CMD_DATA_IN 0xf2 //0X3EA
-#define ATA_CMD_DATA_OUT 0xf3 //0X3EB
-#define ATA_CMD_PACKET 0xf4 //0X3EC
-#define ATAPI_GET_SENSE 0xf5 //0X3ED
-#define ATAPI_IS_READY 0xf6 //0X3EE
-#define ATAPI_IS_CDROM 0xf7 //0X3EF
-
-#define CDEMU_INIT 0xf8 //0X2E8
-#define CDEMU_ISACTIVE 0xf9 //0X2E9
-#define CDEMU_EMULATED_DRIVE 0xfa //0X2EA
-#define CDROM_BOOT 0xfb //0X2EB
-
-
-#define HARD_DRIVE_POST 0xfc //0X2EC
-
-
-#define ATA_DEVICE_NO 0xfd //0X2ED
-#define ATA_DEVICE_TYPE 0xfe //0X2ED
-
-#define INT13_HARDDISK 0xff //0x2ef
-#define INT13_CDROM 0xe0 //0x2f8
-#define INT13_CDEMU 0xe1 //0x2f9
-#define INT13_ELTORITO 0xe2 //0x2fa
-#define INT13_DISKETTE_FUNCTION 0xe3 //0x2fb
-
-
-
-
static const char cdrom_str[] = "CD-ROM";
static const char harddisk_str[] = "HARDDISK";
static const char none_str[] = "NONE";
* 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);
+static void rd_lower_irq(struct vm_device *dev, struct channel_t * channel);
static void rd_print_state(struct ramdisk_t *ramdisk);
static int check_bit_fields(struct controller_t * controller);
#endif
+
+
////////////////////////////////////////////////////////////////////
+int v3_ramdisk_register_cdrom(struct vm_device * dev, uint_t busID, uint_t driveID, struct cdrom_ops* cd, void * private_data) {
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = &(ramdisk->channels[busID]);
+ struct drive_t * drive = &(channel->drives[driveID]);
+ struct controller_t * controller = &(drive->controller);
+
+
+
+ if (drive->device_type != IDE_NONE) {
+ PrintError("Device already registered at this location\n");
+ return -1;
+ }
+
+
+ channel->irq = 15;
+
+ // Make model string
+ strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40);
+
+ while (strlen((char *)(drive->model_no)) < 40) {
+ strcat ((char*)(drive->model_no), " ");
+ }
+
+ PrintDebug("CDROM on target %d/%d\n", busID, driveID);
+
+ drive->device_type = IDE_CDROM;
+ drive->cdrom.locked = 0;
+ drive->sense.sense_key = SENSE_NONE;
+ drive->sense.asc = 0;
+ drive->sense.ascq = 0;
+
+ drive->private_data = private_data;
+
+
+#ifdef DEBUG_RAMDISK
+ if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) {
+ PrintError("interrupt reason: bit field error\n");
+ return INTR_REASON_BIT_ERR;
+ }
+#endif
+
+ controller->sector_count = 0;
+
+ drive->cdrom.cd = cd;
+
+ PrintDebug("\t\tCD on ata%d-%d: '%s'\n",
+ busID,
+ driveID, "");
+
+ if(drive->cdrom.cd->insert_cdrom(drive->private_data)) {
+ PrintDebug("\t\tMedia present in CD-ROM drive\n");
+ drive->cdrom.ready = 1;
+ drive->cdrom.capacity = drive->cdrom.cd->capacity(drive->private_data);
+ PrintDebug("\t\tCDROM capacity is %d\n", drive->cdrom.capacity);
+ } else {
+ PrintDebug("\t\tCould not locate CD-ROM, continuing with media not present\n");
+ drive->cdrom.ready = 0;
+ }
+
+ return 0;
+}
+
+
static Bit32u rd_init_hardware(struct ramdisk_t *ramdisk) {
uint_t channel_num;
uint_t device;
strcat ((char*)(drive->model_no), " ");
}
-
-
-
- if (channel_num == 1) {
-
- channel->ioaddr1 = 0x170;
- channel->ioaddr2 = 0x370;
- channel->irq = 15;
- channel->drive_select = 0;
-
- if (device == 0) {
- // Make model string
- strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40);
- while (strlen((char *)(drive->model_no)) < 40) {
- strcat ((char*)(drive->model_no), " ");
- }
-
- PrintDebug("CDROM on target %d/%d\n", channel_num, device);
-
- drive->device_type = IDE_CDROM;
- drive->cdrom.locked = 0;
- drive->sense.sense_key = SENSE_NONE;
- drive->sense.asc = 0;
- drive->sense.ascq = 0;
-
-#ifdef DEBUG_RAMDISK
- if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) {
- PrintDebug("interrupt reason: bit field error\n");
- return INTR_REASON_BIT_ERR;
- }
-#endif
-
- controller->sector_count = 0;
-
- // allocate low level driver
- drive->cdrom.cd = (struct cdrom_interface *)V3_Malloc(sizeof(struct cdrom_interface));
- PrintDebug("cd = %x\n", drive->cdrom.cd);
- V3_ASSERT(drive->cdrom.cd != NULL);
-
- struct cdrom_interface * cdif = drive->cdrom.cd;
- memset(cdif, 0, sizeof(struct cdrom_interface));
- init_cdrom(cdif);
- cdif->ops.init(cdif);
-
- PrintDebug("\t\tCD on ata%d-%d: '%s'\n",
- channel_num,
- device, "");
-
- if((drive->cdrom.cd->ops).insert_cdrom(cdif, NULL)) {
- PrintDebug("\t\tMedia present in CD-ROM drive\n");
- drive->cdrom.ready = 1;
- drive->cdrom.capacity = drive->cdrom.cd->ops.capacity(cdif);
- } else {
- PrintDebug("\t\tCould not locate CD-ROM, continuing with media not present\n");
- drive->cdrom.ready = 0;
- }
-
- }//if device = 0
- }//if channel = 0
}//for device
}//for channel
controller = &(drive->controller);
- PrintDebug("[read_data_handler] IO Read at 0x%x, on drive %d/%d (current_cmd = 0x%02x)\n",
+ PrintTrace("[read_data_handler] IO Read at 0x%x, on drive %d/%d current cmd=0x%x\n",
port,
get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive),
+ get_drive_no(channel, drive),
controller->current_command);
switch (controller->current_command) {
uint_t index = controller->buffer_index;
- PrintDebug("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n",
+ PrintTrace("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n",
drive->atapi.command,
index,
drive->cdrom.remaining_blocks);
case 0x28: // read (10)
case 0xa8: // read (12)
{
- struct cdrom_interface * cdif = drive->cdrom.cd;
-
+
if (!(drive->cdrom.ready)) {
PrintError("\t\tRead with CDROM not ready\n");
return -1;
}
- drive->cdrom.cd->ops.read_block(cdif, controller->buffer,
- drive->cdrom.next_lba);
+ drive->cdrom.cd->read_block(drive->private_data, controller->buffer,
+ drive->cdrom.next_lba);
drive->cdrom.next_lba++;
drive->cdrom.remaining_blocks--;
}
default:
- PrintDebug("\t\tread need support more command: %02x\n", controller->current_command);
+ PrintError("\t\tunsupported command: %02x\n", controller->current_command);
break;
}
drive = get_selected_drive(channel);
controller = &(drive->controller);
+
PrintDebug("[write_data_handler] IO write at 0x%x, current_cmd = 0x%02x\n",
- port, controller->current_command);
-
+ port, controller->current_command);
+
+
+
+ //PrintDebug("[write_data_handler]\n");
switch (controller->current_command) {
case 0x30: // WRITE SECTORS
PrintError("\t\tneed to implement 0x30(write sector) to port 0x%x\n", port);
case 0xa0: // PACKET
if (handle_atapi_packet_command(dev, channel, *(ushort_t *)src) == -1) {
+ PrintError("Error sending atapi packet command in PACKET write to data port\n");
return -1;
}
return -1;
}
+
+
+ return -1;
}
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]);
drive = get_selected_drive(channel);
controller = &(drive->controller);
+
PrintDebug("[read_status_handler] IO read at 0x%x, on drive %d/%d\n",
port, get_channel_no(ramdisk, channel),
channel->drive_select);
if (num_drives_on_channel(channel) == 0) {
+ PrintDebug("Setting value to zero because 0 devices on channel\n");
// (mch) Just return zero for these registers
memset(dst, 0, length);
(controller->status.corrected_data << 2) |
(controller->status.index_pulse << 1) |
(controller->status.err) );
-
+
+
memcpy(dst, &val, length);
controller->status.index_pulse_count++;
}
if ((port == SEC_CMD_PORT) || (port == PRI_CMD_PORT)) {
- rd_lower_irq(dev, channel->irq);
+ rd_lower_irq(dev, channel);
}
+ PrintDebug("\t\tRead STATUS = 0x%x\n", *(uchar_t *)dst);
+
return length;
}
PrintDebug("[write_command_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n",
port, get_channel_no(ramdisk, channel),
- channel->drive_select,
+ get_drive_no(channel, drive),
value);
switch (value) {
+#if 0
+ case 0xec: // IDENTIFY DEVICE
+ {
+
+ if (drive->device_type == IDE_NONE) {
+ PrintError("\t\tError: disk ata%d-%d not present, aborting\n",
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
+ rd_command_aborted(dev, channel, value);
+ break;
+ } else if (drive->device_type == IDE_CDROM) {
+ PrintDebug("Identifying CDROM...Going to abort????\n");
+ controller->head_no = 0;
+ controller->sector_count = 1;
+ controller->sector_no = 1;
+ controller->cylinder_no = 0xeb14;
+ rd_command_aborted(dev, channel, 0xec);
+ } else {
+ PrintError("\t\tError: Want to identify HDD!!\n");
+ /*
+ SELECTED_CONTROLLER(channel).current_command = value;
+ SELECTED_CONTROLLER(channel).error_register = 0;
+
+ // See ATA/ATAPI-4, 8.12
+ 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;
+ raise_interrupt(channel);
+ identify_drive(channel);
+ */
+ }
+
+ break;
+ }
+#endif
// ATAPI commands
case 0xa1: // IDENTIFY PACKET DEVICE
{
rd_raise_interrupt(dev, channel);
rd_identify_ATAPI_drive(dev, channel);
} else {
+ PrintError("Identifying non cdrom device not supported - ata %d/%d\n",
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
rd_command_aborted(dev, channel, 0xa1);
}
break;
controller->current_command = value;
controller->buffer_index = 0;
} else {
+ PrintError("Sending packet to non cdrom device not supported\n");
rd_command_aborted (dev, channel, 0xa0);
}
break;
}
default:
- PrintError("\t\tneed translate command %2x\n", value);
- return -1;
+ PrintError("\t\tneed translate command %2x - ata %d\%d\n", value,
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
+ //return -1;
+ /* JRL THIS NEEDS TO CHANGE */
+ return length;
}
return length;
prev_control_reset = controller->control.reset;
+
+ if (value & 0x04) {
+ PrintDebug("RESET Signaled\n");
+ }
+
master_drive->controller.control.reset = value & 0x04;
slave_drive->controller.control.reset = value & 0x04;
ctrl->control.disable_irq = 0;
}
- rd_lower_irq(dev, channel->irq);
+ rd_lower_irq(dev, channel);
} else if ((controller->reset_in_progress) &&
(!controller->control.reset)) {
controller->status.err = 0;
+ PrintDebug("\t\tRead FEATURES = 0x%x\n", val);
+
*(uchar_t *)dst = val;
return length;
case SEC_SECT_CNT_PORT: // hard disk sector count / interrupt reason 0x1f2
{
uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_count;
-
+ PrintDebug("\t\tRead SECTOR COUNT = 0x%x\n", val);
*(uchar_t *)dst = val;
return length;
}
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;
+ PrintDebug("\t\tRead SECTOR ADDR1 = 0x%x\n", val);
+
*(uchar_t *)dst = val;
return length;
// to detect the disks.... minix2 for example
uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no & 0x00ff);
+ PrintDebug("\t\tRead SECTOR ADDR2 = 0x%x\n", val);
+
*(uchar_t *)dst = val;
return length;
// to detect the disks.... minix2 for example
uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no >> 8);
+ PrintDebug("\t\tRead SECTOR ADDR3 = 0x%x\n", val);
+
*(uchar_t *)dst = val;
return length;
(channel->drive_select << 4) |
(controller->head_no << 0));
+ PrintDebug("\t\tRead DRIVE SELECT = 0x%x\n", val);
*(uchar_t *)dst = val;
return length;
PrintDebug("[write_general_handler] IO write to port %x (val=0x%02x), channel = %d\n",
- port, value, get_channel_no(ramdisk, channel));
+ port, value, get_channel_no(ramdisk, channel));
switch (port) {
}
write_lba_mode(channel, (value >> 6) & 1);
- drive->cdrom.cd->lba = (value >> 6) & 1;
-
+
+
+
+ if (drive->cdrom.cd) {
+ PrintDebug("\t\tSetting LBA on CDROM: %d\n", (value >> 6) & 1);
+ drive->cdrom.cd->set_LBA(drive->private_data, (value >> 6) & 1);
+ }
+
channel->drive_select = (value >> 4) & 0x01;
drive = get_selected_drive(channel);
if (drive->device_type == IDE_NONE) {
- PrintDebug("\t\tError: device set to %d which does not exist! channel = 0x%x\n",
+ PrintError("\t\tError: device set to %d which does not exist! channel = 0x%x\n",
channel->drive_select, get_channel_no(ramdisk, channel));
controller->error_register = 0x04; // aborted
static void rd_raise_interrupt(struct vm_device * dev, struct channel_t * channel) {
- Bit32u irq;
// struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
struct drive_t * drive = get_selected_drive(channel);
struct controller_t * controller = &(drive->controller);
- PrintDebug("[raise_interrupt] disable_irq = %02x\n", controller->control.disable_irq);
+ PrintDebug("[raise_interrupt] disable_irq = 0x%02x\n", controller->control.disable_irq);
if (!(controller->control.disable_irq)) {
- irq = channel->irq;
- PrintDebug("\t\tRaising interrupt %d {%s}\n\n", irq, device_type_to_str(drive->device_type));
+ PrintDebug("\t\tRaising interrupt %d {%s}\n\n", channel->irq, device_type_to_str(drive->device_type));
- dev->vm->vm_ops.raise_irq(dev->vm, irq);
+ v3_raise_irq(dev->vm, channel->irq);
} else {
- PrintDebug("\t\tirq is disabled\n");
+ PrintDebug("\t\tRaising irq but irq is disabled\n");
}
return;
}
-static void rd_lower_irq(struct vm_device *dev, Bit32u irq) // __attribute__(regparm(1))
-{
- PrintDebug("[lower_irq] irq = %d\n", irq);
- dev->vm->vm_ops.lower_irq(dev->vm, irq);
+static void rd_lower_irq(struct vm_device *dev, struct channel_t * channel) {
+ PrintDebug("[lower_irq] irq = %d\n", channel->irq);
+ v3_lower_irq(dev->vm, channel->irq);
}
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 ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
struct drive_t * drive = get_selected_drive(channel);
struct controller_t * controller = &(drive->controller);
switch (atapi_command) {
case 0x00: // test unit ready
{
+ PrintDebug("Testing unit ready\n");
if (drive->cdrom.ready) {
rd_atapi_cmd_nop(dev, channel);
} else {
+ PrintError("CDROM not ready in test unit ready\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
}
int alloc_length = controller->buffer[4];
if (rd_init_send_atapi_command(dev, channel, atapi_command, 18, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in Request Sense\n");
return -1;
}
rd_atapi_cmd_nop(dev, channel);
rd_raise_interrupt(dev, channel);
+
} else if (!LoEj && Start) { // start (spin up) the disc
- drive->cdrom.cd->ops.start_cdrom(drive->cdrom.cd);
+ drive->cdrom.cd->start_cdrom(drive->private_data);
PrintError("FIXME: ATAPI start disc not reading TOC\n");
rd_atapi_cmd_nop(dev, channel);
rd_raise_interrupt(dev, channel);
+
} else if (LoEj && !Start) { // Eject the disc
rd_atapi_cmd_nop(dev, channel);
-
+ PrintDebug("Ejecting Disk\n");
if (drive->cdrom.ready) {
- drive->cdrom.cd->ops.eject_cdrom(drive->cdrom.cd);
+ drive->cdrom.cd->eject_cdrom(drive->private_data);
drive->cdrom.ready = 0;
//bx_options.atadevice[channel][SLAVE_SELECTED(channel)].Ostatus->set(EJECTED);
//bx_gui->update_drive_status_buttons();
}
rd_raise_interrupt(dev, channel);
+
} else { // Load the disc
// My guess is that this command only closes the tray, that's a no-op for us
rd_atapi_cmd_nop(dev, channel);
}
if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in mechanism status\n");
return -1;
}
{
if (rd_init_send_atapi_command(dev, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in mode sense error recovery\n");
return -1;
}
{
if (rd_init_send_atapi_command(dev, channel, atapi_command, 28, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in CDROM caps/mech mode-sense\n");
return -1;
}
default:
{
// not implemeted by this device
- PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
+ PrintError("\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);
default:
{
// not implemeted by this device
+ PrintError("Changeable values of mode sense not supported by cdrom\n");
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,
case 0x0e: // CD-ROM audio control
case 0x2a: // CD-ROM capabilities & mech. status
case 0x3f: // all
- PrintError("cdrom: MODE SENSE (dflt), code=%x\n",
+ PrintError("Default values of mode sense not supported by cdrom\n");
+ PrintDebug("cdrom: MODE SENSE (dflt), code=%x\n",
PageCode);
return -1;
default:
{
+ PrintError("Default values of mode sense not implemented in cdrom\n");
// not implemeted by this device
- PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
- PC, PageCode);
+ PrintDebug("cdrom: 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);
}
case 0x3: // saved values not implemented
{
+ PrintError("\t\tSaved values not implemented in mode sense\n");
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
rd_raise_interrupt(dev, channel);
break;
}
default:
{
- PrintError("Should not get here!\n");
+ PrintError("Unsupported Mode sense value\n");
return -1;
break;
}
uint8_t alloc_length = controller->buffer[4];
if (rd_init_send_atapi_command(dev, channel, atapi_command, 36, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in inquiry\n");
return -1;
}
{
// no allocation length???
if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, 8, false) == -1) {
+ PrintError("Error sending atapi command in read cdrom capacity\n");
return -1;
}
rd_ready_to_send_atapi(dev, channel);
} else {
+ PrintError("CDROM not ready in read cdrom capacity\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
rd_raise_interrupt(dev, channel);
}
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
rd_raise_interrupt(dev, channel);
} else {
+ PrintError("Drive not ready in read cd with CD present\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
rd_raise_interrupt(dev, channel);
}
case 0x43: // read toc
{
if (drive->cdrom.ready) {
- int toc_length;
+ int toc_length = 0;
bool msf = (controller->buffer[1] >> 1) & 1;
uint8_t starting_track = controller->buffer[6];
uint8_t format = (controller->buffer[9] >> 6);
int i;
+
+ PrintDebug("Reading CDROM TOC: Format=%d (byte count=%d) (toc length:%d)\n",
+ format, controller->byte_count, toc_length);
+
switch (format) {
case 0:
-
- 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 {
+ {
+ if (!(drive->cdrom.cd->read_toc(drive->private_data, controller->buffer,
+ &toc_length, msf, starting_track))) {
+ PrintError("CDROM: Reading Table of Contents Failed\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+
+
if (rd_init_send_atapi_command(dev, channel, atapi_command, toc_length, alloc_length, false) == -1) {
+ PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
return -1;
}
- rd_ready_to_send_atapi(dev, channel);
+
+ rd_ready_to_send_atapi(dev, channel);
+
+ break;
}
- break;
-
case 1:
// multi session stuff. we ignore this and emulate a single session only
+
if (rd_init_send_atapi_command(dev, channel, atapi_command, 12, alloc_length, false) == -1) {
+ PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
return -1;
}
return -1;
}
} else {
+ PrintError("CDROM not ready in read toc\n");
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 lba = rd_read_32bit(controller->buffer + 2);
if (!(drive->cdrom.ready)) {
+ PrintError("CDROM Error: Not Ready (ATA%d/%d)\n",
+ get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
rd_raise_interrupt(dev, channel);
break;
}
if (transfer_length == 0) {
+ PrintError("READ(%d) with transfer length 0, ok\n",
+ (atapi_command == 0x28) ? 10 : 12);
rd_atapi_cmd_nop(dev, channel);
rd_raise_interrupt(dev, channel);
- PrintDebug("\t\tREAD(%d) with transfer length 0, ok\n", (atapi_command == 0x28) ? 10 : 12);
break;
}
if (lba + transfer_length > drive->cdrom.capacity) {
+ PrintError("CDROM Error: Capacity exceeded [capacity=%d] (ATA%d/%d)\n",
+ drive->cdrom.capacity,
+ get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
rd_raise_interrupt(dev, channel);
break;
// handle command
if (rd_init_send_atapi_command(dev, channel, atapi_command, transfer_length * 2048,
transfer_length * 2048, true) == -1) {
+ PrintError("CDROM Error: Atapi command send error\n");
return -1;
}
+
drive->cdrom.remaining_blocks = transfer_length;
drive->cdrom.next_lba = lba;
rd_ready_to_send_atapi(dev, channel);
uint32_t lba = rd_read_32bit(controller->buffer + 2);
if (!(drive->cdrom.ready)) {
+ PrintError("CDROM not ready in seek\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
rd_raise_interrupt(dev, channel);
break;
}
if (lba > drive->cdrom.capacity) {
+ PrintError("LBA is greater than CDROM capacity in seek\n");
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
rd_raise_interrupt(dev, channel);
break;
}
- PrintDebug("\t\tcdrom: SEEK (ignored)\n");
+ PrintError("\t\tcdrom: SEEK (ignored)\n");
rd_atapi_cmd_nop(dev, channel);
rd_raise_interrupt(dev, channel);
drive->cdrom.locked = controller->buffer[4] & 1;
rd_atapi_cmd_nop(dev, channel);
} else {
+ PrintError("CD not ready in prevent/allow medium removal\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
}
UNUSED(track_number);
*/
if (!(drive->cdrom.ready)) {
+ PrintError("CDROM not ready in read sub-channel\n");
rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
rd_raise_interrupt(dev, channel);
} else {
}
if (rd_init_send_atapi_command(dev, channel, atapi_command, ret_len, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in read sub-channel\n");
return -1;
}
rd_ready_to_send_atapi(dev, channel);
case 0x51: // read disc info
{
// no-op to keep the Linux CD-ROM driver happy
+ PrintError("Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
rd_raise_interrupt(dev, channel);
break;
case 0x46: // ???
case 0x4a: // ???
PrintError("ATAPI command 0x%x not implemented yet\n",
- atapi_command);
+ atapi_command);
rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
rd_raise_interrupt(dev, channel);
break;
break;
}
}
+
+
return 0;
}
!(alloc_length <= controller->byte_count)) {
PrintDebug("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n",
- controller->byte_count,
- command,
- controller->byte_count - 1);
+ controller->byte_count,
+ command,
+ controller->byte_count - 1);
controller->byte_count -= 1;
}
- void rd_ready_to_send_atapi(struct vm_device * dev, struct channel_t * channel) {
+void rd_ready_to_send_atapi(struct vm_device * dev, struct channel_t * channel) {
PrintDebug("[rd_ready_to_send_atapi]\n");
-
+
rd_raise_interrupt(dev, channel);
}
struct drive_t * drive = &(channel->drives[channel->drive_select]);
struct controller_t * controller = &(drive->controller);
-#ifdef DEBUG_RAMDISK
- {
- struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
- PrintDebug("[rd_atapi_cmd_error]\n");
- PrintDebug("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n",
- get_channel_no(ramdisk, channel), sense_key, asc);
- }
-#endif
+
+ struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
+ PrintError("[rd_atapi_cmd_error]\n");
+ PrintError("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n",
+ get_channel_no(ramdisk, channel), sense_key, asc);
+
controller->error_register = sense_key << 4;
controller->interrupt_reason.i_o = 1;
struct drive_t * drive = &(channel->drives[channel->drive_select]);
struct controller_t * controller = &(drive->controller);
- PrintDebug("[rd_command_aborted]\n");
- PrintDebug("\t\taborting on command 0x%02x {%s}\n", value, device_type_to_str(drive->device_type));
+ PrintError("[rd_command_aborted]\n");
+ PrintError("\t\taborting on command 0x%02x {%s}\n", value, device_type_to_str(drive->device_type));
controller->current_command = 0;
controller->status.busy = 0;
rd_init_hardware(ramdisk);
- dev_hook_io(dev, PRI_CTRL_PORT,
- &read_status_port, &write_ctrl_port);
-
- dev_hook_io(dev, PRI_DATA_PORT,
- &read_data_port, &write_data_port);
- dev_hook_io(dev, PRI_FEATURES_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_SECT_CNT_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_SECT_ADDR1_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_SECT_ADDR2_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_SECT_ADDR3_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_DRV_SEL_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, PRI_CMD_PORT,
- &read_status_port, &write_cmd_port);
-
-
- dev_hook_io(dev, SEC_CTRL_PORT,
- &read_status_port, &write_ctrl_port);
-
- dev_hook_io(dev, SEC_DATA_PORT,
- &read_data_port, &write_data_port);
- dev_hook_io(dev, SEC_FEATURES_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_SECT_CNT_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_SECT_ADDR1_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_SECT_ADDR2_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_SECT_ADDR3_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_DRV_SEL_PORT,
- &read_general_port, &write_general_port);
- dev_hook_io(dev, SEC_CMD_PORT,
- &read_status_port, &write_cmd_port);
-
+ v3_dev_hook_io(dev, PRI_CTRL_PORT,
+ &read_status_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, PRI_DATA_PORT,
+ &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, PRI_FEATURES_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_CNT_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR1_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR2_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR3_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_DRV_SEL_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_CMD_PORT,
+ &read_status_port, &write_cmd_port);
+
+
+ v3_dev_hook_io(dev, SEC_CTRL_PORT,
+ &read_status_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, SEC_DATA_PORT,
+ &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, SEC_FEATURES_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_CNT_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR1_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR2_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR3_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_DRV_SEL_PORT,
+ &read_general_port, &write_general_port);
+ v3_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);
+ v3_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);
+ v3_dev_hook_io(dev, PRI_ADDR_REG_PORT,
+ &read_general_port, &write_general_port);
-struct vm_device *create_ramdisk()
+struct vm_device * v3_create_ramdisk()
{
struct ramdisk_t *ramdisk;
PrintDebug("[create_ramdisk]\n");
- struct vm_device *device = create_device("RAMDISK", &dev_ops, ramdisk);
+ struct vm_device * device = v3_create_device("RAMDISK", &dev_ops, ramdisk);
return device;
}
return;
}
-#if 0
-static void trace_info(ushort_t port, void *src, uint_t length) {
- switch(port){
- case 0x3e8:
- if (length == 1 && *((uchar_t*) src) == ATA_DETECT)
- PrintDebug("ata_detect()\n");
- break;
-
- case 0x3e9:
- if (length == 1 && *((uchar_t*) src) == ATA_RESET)
- PrintDebug("ata_reset()\n");
- break;
-
- case 0x3ea:
- if (length == 1 && *((uchar_t*) src) == ATA_CMD_DATA_IN)
- PrintDebug("ata_cmd_data_in()\n");
- break;
-
- case 0x3eb:
- if (length == 1 && *((uchar_t*) src) == ATA_CMD_DATA_OUT)
- PrintDebug("ata_cmd_data_out()\n");
- break;
-
- case 0x3ec:
- if (length == 1 && *((uchar_t*) src) == ATA_CMD_PACKET)
- PrintDebug("ata_cmd_packet()\n");
- break;
-
- case 0x3ed:
- if (length == 1 && *((uchar_t*) src) == ATAPI_GET_SENSE)
- PrintDebug("atapi_get_sense()\n");
- break;
-
- case 0x3ee:
- if (length == 1 && *((uchar_t*) src) == ATAPI_IS_READY)
- PrintDebug("atapi_is_ready()\n");
- break;
-
- case 0x3ef:
- if (length == 1 && *((uchar_t*) src) == ATAPI_IS_CDROM)
- PrintDebug("atapi_is_cdrom()\n");
- break;
-
-
- case 0x2e8:
- if (length == 1 && *((uchar_t*) src) == CDEMU_INIT)
- PrintDebug("cdemu_init()\n");
- break;
-
- case 0x2e9:
- if (length == 1 && *((uchar_t*) src) == CDEMU_ISACTIVE)
- PrintDebug("cdemu_isactive()\n");
- break;
-
- case 0x2ea:
- if (length == 1 && *((uchar_t*) src) == CDEMU_EMULATED_DRIVE)
- PrintDebug("cdemu_emulated_drive()\n");
- break;
-
- case 0x2eb:
- if (length == 1 && *((uchar_t*) src) == CDROM_BOOT)
- PrintDebug("cdrom_boot()\n");
- break;
-
- case 0x2ec:
- if (length == 1 && *((uchar_t*) src) == HARD_DRIVE_POST)
- PrintDebug("ata_hard_drive_post()\n");
- break;
-
- case 0x2ed:
- if (length == 1)
- PrintDebug("ata_device_no(%d)\n", *((uchar_t*) src));
- break;
-
- case 0x2ee:
- if (length == 1)
- PrintDebug("ata_device_type(%d)\n", *((uchar_t*) src));
- break;
-
- case 0x2ef:
- if (length == 1 && *((uchar_t*) src) == INT13_HARDDISK)
- PrintDebug("int13_harddrive()\n");
- break;
-
- case 0x2f8:
- if (length == 1 && *((uchar_t*) src) == INT13_CDROM)
- PrintDebug("int13_cdrom()\n");
- break;
-
- case 0x2f9:
- if (length == 1 && *((uchar_t*) src) == INT13_CDEMU)
- PrintDebug("int13_cdemu()\n");
- break;
-
- case 0x2fa:
- if (length == 1 && *((uchar_t*) src) == INT13_ELTORITO)
- PrintDebug("int13_eltorito()\n");
- break;
-
- case 0x2fb:
- if (length == 1 && *((uchar_t*) src) == INT13_DISKETTE_FUNCTION)
- PrintDebug("int13_diskette_function()\n");
- break;
-
-
- default:
- break;
- }
-}
-
-#endif
static int check_bit_fields(struct controller_t * controller) {
//Check bit fields
return 0;
}
+
#endif