Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added ATA PIO write, other ide cleanup
Kyle Hale [Tue, 7 Jan 2014 23:31:45 +0000 (17:31 -0600)]
palacios/src/devices/ata.h
palacios/src/devices/atapi.h
palacios/src/devices/ide.c

index 49637c1..0f9c8df 100644 (file)
@@ -17,6 +17,9 @@
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
+#ifndef _DEVICES_ATA_H_
+#define _DEVICES_ATA_H_
+
 #define MAX_MULT_SECTORS  255
 
 
@@ -127,6 +130,7 @@ static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uin
 }
 
 
+
 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
     struct ide_drive * drive = get_selected_drive(channel);
 
@@ -182,6 +186,34 @@ static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel,
 
 
 // 28 bit LBA
+static int ata_write_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
+
+    if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
+        ide_abort_command(ide, channel);
+        return 0;
+    }
+
+    drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
+    drive->transfer_index = 0;
+    channel->status.busy = 0;
+    channel->status.ready = 0;
+    channel->status.write_fault = 0;
+    channel->status.data_req = 1;
+    channel->status.error = 0;
+
+    drive->irq_flags.io_dir = 1;
+    drive->irq_flags.c_d = 0;
+    drive->irq_flags.rel = 0;
+
+    PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
+
+    return 0;
+}
+
+
+// 28 bit LBA
 static int ata_read_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
@@ -230,3 +262,5 @@ static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel *
 
     return -1;
 }
+
+#endif
index f202d6d..7667e97 100644 (file)
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
+#ifndef __DEVICES_ATAPI_H__
+#define __DEVICES_ATAPI_H__
+
 #define ATAPI_PACKET_SIZE 12
 
 #include "atapi-types.h"
 
 
+/* ACS-2 T13/2015-D Table B.2 Command codes */
+#define ATAPI_NOP                              0x00
+#define CFA_REQ_EXT_ERROR_CODE         0x03 
+#define ATAPI_DSM                         0x06
+#define ATAPI_DEVICE_RESET             0x08
+#define ATAPI_RECAL                       0x10 
+#define ATAPI_READ                     0x20 
+#define ATAPI_READ_ONCE                   0x21 
+#define ATAPI_READ_EXT                 0x24 
+#define ATAPI_READDMA_EXT                      0x25 
+#define ATAPI_READDMA_QUEUED_EXT          0x26 
+#define ATAPI_READ_NATIVE_MAX_EXT              0x27 
+#define ATAPI_MULTREAD_EXT             0x29 
+#define ATAPI_WRITE                    0x30 
+#define ATAPI_WRITE_ONCE                  0x31 
+#define ATAPI_WRITE_EXT                        0x34 
+#define ATAPI_WRITEDMA_EXT             0x35 
+#define ATAPI_WRITEDMA_QUEUED_EXT              0x36 
+#define ATAPI_SET_MAX_EXT                 0x37 
+#define ATAPI_SET_MAX_EXT                      0x37 
+#define CFA_WRITE_SECT_WO_ERASE                0x38 
+#define ATAPI_MULTWRITE_EXT            0x39 
+#define ATAPI_WRITE_VERIFY                0x3C 
+#define ATAPI_VERIFY                   0x40 
+#define ATAPI_VERIFY_ONCE                 0x41 
+#define ATAPI_VERIFY_EXT                       0x42 
+#define ATAPI_SEEK                        0x70 
+#define CFA_TRANSLATE_SECTOR           0x87 
+#define ATAPI_DIAGNOSE                 0x90
+#define ATAPI_SPECIFY                     0x91 
+#define ATAPI_DOWNLOAD_MICROCODE               0x92
+#define ATAPI_STANDBYNOW2                 0x94 
+#define ATAPI_IDLEIMMEDIATE2              0x95 
+#define ATAPI_STANDBY2                    0x96 
+#define ATAPI_SETIDLE2                    0x97 
+#define ATAPI_CHECKPOWERMODE2             0x98 
+#define ATAPI_SLEEPNOW2                   0x99 
+#define ATAPI_PACKETCMD                        0xA0 
+#define ATAPI_PIDENTIFY                        0xA1 
+#define ATAPI_QUEUED_SERVICE              0xA2 
+#define ATAPI_SMART                    0xB0 
+#define CFA_ACCESS_METADATA_STORAGE    0xB8
+#define CFA_ERASE_SECTORS              0xC0 
+#define ATAPI_MULTREAD                 0xC4 
+#define ATAPI_MULTWRITE                        0xC5 
+#define ATAPI_SETMULT                  0xC6 
+#define ATAPI_READDMA                  0xC8 
+#define ATAPI_READDMA_ONCE                0xC9 
+#define ATAPI_WRITEDMA                 0xCA 
+#define ATAPI_WRITEDMA_ONCE               0xCB 
+#define ATAPI_WRITEDMA_QUEUED          0xCC 
+#define CFA_WRITE_MULTI_WO_ERASE       0xCD 
+#define ATAPI_GETMEDIASTATUS              0xDA 
+#define ATAPI_DOORLOCK                    0xDE 
+#define ATAPI_DOORUNLOCK                  0xDF 
+#define ATAPI_STANDBYNOW1                      0xE0
+#define ATAPI_IDLEIMMEDIATE            0xE1 
+#define ATAPI_STANDBY                  0xE2 
+#define ATAPI_SETIDLE1                 0xE3
+#define ATAPI_READ_BUFFER                      0xE4 
+#define ATAPI_CHECKPOWERMODE1          0xE5
+#define ATAPI_SLEEPNOW1                        0xE6
+#define ATAPI_FLUSH_CACHE                      0xE7
+#define ATAPI_WRITE_BUFFER             0xE8 
+#define ATAPI_FLUSH_CACHE_EXT          0xEA 
+#define ATAPI_IDENTIFY                 0xEC 
+#define ATAPI_MEDIAEJECT                  0xED 
+#define ATAPI_SETFEATURES                      0xEF 
+#define IBM_SENSE_CONDITION             0xF0 
+#define ATAPI_SECURITY_SET_PASS                0xF1
+#define ATAPI_SECURITY_UNLOCK          0xF2
+#define ATAPI_SECURITY_ERASE_PREPARE   0xF3
+#define ATAPI_SECURITY_ERASE_UNIT              0xF4
+#define ATAPI_SECURITY_FREEZE_LOCK     0xF5
+#define CFA_WEAR_LEVEL                  0xF5 
+#define ATAPI_SECURITY_DISABLE         0xF6
+
 /* ATAPI sucks...
  * The OS will write to the cylinder register the number of bytes it wants to read 
  * however the device can change that value 
@@ -723,3 +803,5 @@ static void atapi_identify_device(struct ide_drive * drive) {
     /* Disabled until command packet DMA is fixed */
     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
 }
+
+#endif
index e0da650..855549f 100644 (file)
@@ -808,7 +808,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
     
     switch (channel->cmd_reg) {
 
-       case 0xa1: // ATAPI Identify Device Packet
+       case ATAPI_PIDENTIFY: // ATAPI Identify Device Packet
            if (drive->drive_type != BLOCK_CDROM) {
                drive_reset(drive);
 
@@ -824,7 +824,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
                ide_raise_irq(ide, channel);
            }
            break;
-       case 0xec: // Identify Device
+       case ATAPI_IDENTIFY: // Identify Device
            if (drive->drive_type != BLOCK_DISK) {
                drive_reset(drive);
 
@@ -840,7 +840,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            }
            break;
 
-       case 0xa0: // ATAPI Command Packet
+       case ATAPI_PACKETCMD: // ATAPI Command Packet
            if (drive->drive_type != BLOCK_CDROM) {
                ide_abort_command(ide, channel);
            }
@@ -852,14 +852,14 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            channel->status.data_req = 1;
            channel->status.error = 0;
 
-           // reset the data buffer...
+           // reset the datxgoto-la buffer...
            drive->transfer_length = ATAPI_PACKET_SIZE;
            drive->transfer_index = 0;
 
            break;
 
-       case 0x20: // Read Sectors with Retry
-       case 0x21: // Read Sectors without Retry
+       case ATAPI_READ: // Read Sectors with Retry
+       case ATAPI_READ_ONCE: // Read Sectors without Retry
            drive->hd_state.cur_sector_num = 1;
 
            if (ata_read_sectors(ide, channel) == -1) {
@@ -868,7 +868,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            }
            break;
 
-       case 0x24: // Read Sectors Extended
+       case ATAPI_READ_EXT: // Read Sectors Extended
            drive->hd_state.cur_sector_num = 1;
 
            if (ata_read_sectors_ext(ide, channel) == -1) {
@@ -877,8 +877,20 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            }
            break;
 
-       case 0xc8: // Read DMA with retry
-       case 0xc9: { // Read DMA
+       case ATAPI_WRITE: {// Write Sector
+           drive->hd_state.cur_sector_num = 1;
+
+           if (ata_write_sectors(ide, channel) == -1) {
+               PrintError(core->vm_info, core, "Error writing sectors\n");
+               return -1;
+           }
+           break;
+       }
+
+           
+
+       case ATAPI_READDMA: // Read DMA with retry
+       case ATAPI_READDMA_ONCE: { // Read DMA
            uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
            if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
@@ -901,7 +913,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            break;
        }
 
-       case 0xca: { // Write DMA
+       case ATAPI_WRITEDMA: { // Write DMA
            uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
            if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
@@ -923,22 +935,22 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            }
            break;
        }
-       case 0xe0: // Standby Now 1
-       case 0xe1: // Set Idle Immediate
-       case 0xe2: // Standby
-       case 0xe3: // Set Idle 1
-       case 0xe6: // Sleep Now 1
-       case 0x94: // Standby Now 2
-       case 0x95: // Idle Immediate (CFA)
-       case 0x96: // Standby 2
-       case 0x97: // Set idle 2
-       case 0x99: // Sleep Now 2
+       case ATAPI_STANDBYNOW1: // Standby Now 1
+       case ATAPI_IDLEIMMEDIATE: // Set Idle Immediate
+       case ATAPI_STANDBY: // Standby
+       case ATAPI_SETIDLE1: // Set Idle 1
+       case ATAPI_SLEEPNOW1: // Sleep Now 1
+       case ATAPI_STANDBYNOW2: // Standby Now 2
+       case ATAPI_IDLEIMMEDIATE2: // Idle Immediate (CFA)
+       case ATAPI_STANDBY2: // Standby 2
+       case ATAPI_SETIDLE2: // Set idle 2
+       case ATAPI_SLEEPNOW2: // Sleep Now 2
            channel->status.val = 0;
            channel->status.ready = 1;
            ide_raise_irq(ide, channel);
            break;
 
-       case 0xef: // Set Features
+       case ATAPI_SETFEATURES: // Set Features
            // Prior to this the features register has been written to. 
            // This command tells the drive to check if the new value is supported (the value is drive specific)
            // Common is that bit0=DMA enable
@@ -955,14 +967,14 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            ide_raise_irq(ide, channel);
            break;
 
-       case 0x91:  // Initialize Drive Parameters
-       case 0x10:  // recalibrate?
+       case ATAPI_SPECIFY:  // Initialize Drive Parameters
+       case ATAPI_RECAL:  // recalibrate?
            channel->status.error = 0;
            channel->status.ready = 1;
            channel->status.seek_complete = 1;
            ide_raise_irq(ide, channel);
            break;
-       case 0xc6: { // Set multiple mode (IDE Block mode) 
+       case ATAPI_SETMULT: { // Set multiple mode (IDE Block mode) 
            // This makes the drive transfer multiple sectors before generating an interrupt
            uint32_t tmp_sect_num = drive->sector_num; // GCC SUCKS
 
@@ -985,7 +997,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            break;
        }
 
-       case 0x08: // Reset Device
+       case ATAPI_DEVICE_RESET: // Reset Device
            drive_reset(drive);
            channel->error_reg.val = 0x01;
            channel->status.busy = 0;
@@ -995,7 +1007,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            channel->status.error = 0;
            break;
 
-       case 0xe5: // Check power mode
+       case ATAPI_CHECKPOWERMODE1: // Check power mode
            drive->sector_count = 0xff; /* 0x00=standby, 0x80=idle, 0xff=active or idle */
            channel->status.busy = 0;
            channel->status.ready = 1;
@@ -1004,7 +1016,7 @@ static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, u
            channel->status.error = 0;
            break;
 
-       case 0xc4:  // read multiple sectors
+       case ATAPI_MULTREAD:  // read multiple sectors
            drive->hd_state.cur_sector_num = drive->hd_state.mult_sector_num;
        default:
            PrintError(core->vm_info, core, "Unimplemented IDE command (%x)\n", channel->cmd_reg);
@@ -1020,29 +1032,44 @@ static int write_data_port(struct guest_info * core, ushort_t port, void * src,
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
 
-    //    PrintDebug(core->vm_info, core, "IDE: Writing Data Port %x (val=%x, len=%d)\n", 
-    //        port, *(uint32_t *)src, length);
-    
+    PrintDebug(core->vm_info, core, "IDE: Writing Data Port %x (val=%x, len=%d)\n", 
+            port, *(uint32_t *)src, length);
+
     memcpy(drive->data_buf + drive->transfer_index, src, length);    
     drive->transfer_index += length;
 
     // Transfer is complete, dispatch the command
     if (drive->transfer_index >= drive->transfer_length) {
-       switch (channel->cmd_reg) {
-           case 0x30: // Write Sectors
-               PrintError(core->vm_info, core, "Writing Data not yet implemented\n");
-               return -1;
-               
-           case 0xa0: // ATAPI packet command
-               if (atapi_handle_packet(core, ide, channel) == -1) {
-                   PrintError(core->vm_info, core, "Error handling ATAPI packet\n");
-                   return -1;
-               }
-               break;
-           default:
-               PrintError(core->vm_info, core, "Unhandld IDE Command %x\n", channel->cmd_reg);
-               return -1;
-       }
+        switch (channel->cmd_reg) {
+
+            case ATAPI_WRITE: // Write Sectors
+
+                channel->status.busy = 1;
+                channel->status.data_req = 0;
+                    
+                if (ata_write(ide, channel, drive->data_buf, drive->transfer_length/HD_SECTOR_SIZE) == -1) {
+                    PrintError(core->vm_info, core, "Error writing to disk\n");
+                    return -1;
+                }
+
+                PrintDebug(core->vm_info, core, "IDE: Write sectors complete\n");
+
+                channel->status.error = 0;
+                channel->status.busy = 0;
+
+                ide_raise_irq(ide, channel);
+                break;
+
+            case ATAPI_PACKETCMD: // ATAPI packet command
+                if (atapi_handle_packet(core, ide, channel) == -1) {
+                    PrintError(core->vm_info, core, "Error handling ATAPI packet\n");
+                    return -1;
+                }
+                break;
+            default:
+                PrintError(core->vm_info, core, "Unhandld IDE Command %x\n", channel->cmd_reg);
+                return -1;
+        }
     }
 
     return length;