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.


lots of fixes
[palacios.git] / palacios / src / devices / ata.h
index b759f0b..cb0193e 100644 (file)
@@ -17,6 +17,8 @@
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
+#define MAX_MULT_SECTORS  255
+
 
 static void ata_identify_device(struct ide_drive * drive) {
     struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
@@ -39,11 +41,11 @@ static void ata_identify_device(struct ide_drive * drive) {
     drive_id->cdrom_flag = 0;
 
     // Make it the simplest drive possible (1 head, 1 cyl, 1 sect/track)
-    drive_id->num_cylinders = 1;
-    drive_id->num_heads = 1;
-    drive_id->bytes_per_track = IDE_SECTOR_SIZE;
-    drive_id->bytes_per_sector = IDE_SECTOR_SIZE;
-    drive_id->sectors_per_track = 1;
+    drive_id->num_cylinders = drive->num_cylinders;
+    drive_id->num_heads = drive->num_heads;
+    drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE;
+    drive_id->bytes_per_sector = HD_SECTOR_SIZE;
+    drive_id->sectors_per_track = drive->num_sectors;
 
 
     // These buffers do not contain a terminating "\0"
@@ -54,6 +56,7 @@ static void ata_identify_device(struct ide_drive * drive) {
     // 32 bits access
     drive_id->dword_io = 1;
 
+
     // enable DMA access
     drive_id->dma_enable = 1;
 
@@ -61,19 +64,26 @@ static void ata_identify_device(struct ide_drive * drive) {
     drive_id->lba_enable = 1;
     
     // Drive Capacity (28 bit LBA)
-    drive_id->lba_capacity = drive->hd_ops->get_capacity(drive->private_data);
+    drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
     
     // Drive Capacity (48 bit LBA)
-    drive_id->lba_capacity_2 = drive->hd_ops->get_capacity(drive->private_data);
+    drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
+
+
+    // lower byte is the maximum multiple sector size...
+    drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
+
 
-    drive_id->rw_multiples = 0x80ff;
 
     // words 64-70, 54-58 valid
     drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
 
+
     // copied from CFA540A
-    drive_id->buf[63] = 0x0103; // variable (DMA stuff)
+    // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
     //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
+    drive_id->buf[63] = 0x0007;
+
     
     //    drive_id->buf[64] = 0x0001; // PIO
     drive_id->buf[65] = 0x00b4;
@@ -87,14 +97,16 @@ static void ata_identify_device(struct ide_drive * drive) {
     //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
     drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
 
+
     drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
 
 
     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
+
 }
 
 
-static int ata_read(struct vm_device * dev, struct ide_channel * channel) {
+static int ata_read(struct vm_device * dev, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     if (drive->hd_state.accessed == 0) {
@@ -102,7 +114,9 @@ static int ata_read(struct vm_device * dev, struct ide_channel * channel) {
        drive->hd_state.accessed = 1;
     }
 
-    int ret = drive->hd_ops->read(drive->data_buf, 1, drive->current_lba, drive->private_data);
+    PrintDebug("Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
+
+    int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
     
     if (ret == -1) {
        PrintError("IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
@@ -110,12 +124,30 @@ static int ata_read(struct vm_device * dev, struct ide_channel * channel) {
     }
 
     return 0;
+
+
+
 }
 
 
+static int ata_write(struct vm_device * dev, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
+    struct ide_drive * drive = get_selected_drive(channel);
 
-// 28 bit LBA
-static int ata_read_sectors(struct vm_device * dev, struct ide_channel * channel) {
+    PrintDebug("Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
+
+    int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
+
+    if (ret == -1) {
+       PrintError("IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
+       return -1;
+    }
+
+    return 0;
+}
+
+
+
+static int ata_get_lba(struct vm_device * dev, struct ide_channel * channel, uint64_t * lba) {
     struct ide_drive * drive = get_selected_drive(channel);
     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
@@ -137,28 +169,39 @@ static int ata_read_sectors(struct vm_device * dev, struct ide_channel * channel
     lba_addr.buf[2] = drive->lba2;
     lba_addr.buf[3] = channel->drive_head.lba3;
 
-    PrintDebug("LBA Address %d\n", drive->lba0);
-    PrintDebug("sector_num %d\n", drive->sector_num);
-
 
-    if (lba_addr.addr + (sect_cnt * IDE_SECTOR_SIZE) > 
-       drive->hd_ops->get_capacity(drive->private_data)) {
+    if ((lba_addr.addr + sect_cnt) > 
+       drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
        PrintError("IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n", 
                   lba_addr.addr, sect_cnt, 
-                  lba_addr.addr + (sect_cnt * IDE_SECTOR_SIZE),
-                  (void *)(addr_t)(drive->hd_ops->get_capacity(drive->private_data)));
+                  lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE),
+                  (void *)(addr_t)(drive->ops->get_capacity(drive->private_data)));
+       return -1;
+    }
+
+    *lba = lba_addr.addr;
+    return 0;
+}
+
+
+// 28 bit LBA
+static int ata_read_sectors(struct vm_device * dev, 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)
+    uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
+
+    if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) {
        ide_abort_command(dev, channel);
        return 0;
     }
 
-    drive->current_lba = lba_addr.addr;
     
-    if (ata_read(dev, channel) == -1) {
+    if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
        PrintError("Could not read disk sector\n");
        return -1;
     }
 
-    drive->transfer_length = sect_cnt * IDE_SECTOR_SIZE;
+    drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
     drive->transfer_index = 0;
 
     channel->status.busy = 0;