2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #ifndef _DEVICES_ATA_H_
21 #define _DEVICES_ATA_H_
23 #define MAX_MULT_SECTORS 255
26 static void ata_identify_device(struct ide_drive * drive) {
27 struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
28 const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
29 const char* firmware = "ALPHA1 ";
31 drive->transfer_length = 512;
32 drive->transfer_index = 0;
35 memset(drive_id->buf, 0, sizeof(drive_id->buf));
37 drive_id->fixed_drive = 1;
38 drive_id->removable_media = 0;
41 drive_id->disk_speed1 = 1;
42 drive_id->disk_speed3 = 1;
44 drive_id->cdrom_flag = 0;
46 // Make it the simplest drive possible (1 head, 1 cyl, 1 sect/track)
47 drive_id->num_cylinders = drive->num_cylinders;
48 drive_id->num_heads = drive->num_heads;
49 drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE;
50 drive_id->bytes_per_sector = HD_SECTOR_SIZE;
51 drive_id->sectors_per_track = drive->num_sectors;
54 // These buffers do not contain a terminating "\0"
55 memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
56 memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
57 memcpy(drive_id->model_num, drive->model, 40);
60 drive_id->dword_io = 1;
64 drive_id->dma_enable = 1;
67 drive_id->lba_enable = 1;
69 // Drive Capacity (28 bit LBA)
70 drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
72 // Drive Capacity (48 bit LBA)
73 drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
76 // lower byte is the maximum multiple sector size...
77 drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
81 // words 64-70, 54-58 valid
82 drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
85 // copied from CFA540A
86 // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
87 //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
88 drive_id->buf[63] = 0x0007;
91 // drive_id->buf[64] = 0x0001; // PIO
92 drive_id->buf[65] = 0x00b4;
93 drive_id->buf[66] = 0x00b4;
94 drive_id->buf[67] = 0x012c;
95 drive_id->buf[68] = 0x00b4;
97 drive_id->buf[71] = 30; // faked
98 drive_id->buf[72] = 30; // faked
100 // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
101 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
104 drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
107 drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
112 static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
113 struct ide_drive * drive = get_selected_drive(channel);
115 if (drive->hd_state.accessed == 0) {
116 drive->current_lba = 0;
117 drive->hd_state.accessed = 1;
120 PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
122 int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
125 PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
134 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
135 struct ide_drive * drive = get_selected_drive(channel);
137 PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
139 int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
142 PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
151 static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba) {
152 struct ide_drive * drive = get_selected_drive(channel);
153 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
154 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
159 } __attribute__((packed)) lba_addr;
162 0-8: sector number reg (drive->lba0)
163 8-16: low cylinder reg (drive->lba1)
164 16-24: high cylinder reg (drive->lba2)
165 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num)
168 lba_addr.buf[0] = drive->lba0;
169 lba_addr.buf[1] = drive->lba1;
170 lba_addr.buf[2] = drive->lba2;
171 lba_addr.buf[3] = channel->drive_head.lba3;
174 if ((lba_addr.addr + sect_cnt) >
175 drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
176 PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n",
177 lba_addr.addr, sect_cnt,
178 lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE),
179 (void *)(addr_t)(drive->ops->get_capacity(drive->private_data)));
183 *lba = lba_addr.addr;
189 static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * channel) {
190 struct ide_drive * drive = get_selected_drive(channel);
191 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
193 if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
194 ide_abort_command(ide, channel);
198 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
199 drive->transfer_index = 0;
200 channel->status.busy = 0;
201 channel->status.ready = 0;
202 channel->status.write_fault = 0;
203 channel->status.data_req = 1;
204 channel->status.error = 0;
206 drive->irq_flags.io_dir = 1;
207 drive->irq_flags.c_d = 0;
208 drive->irq_flags.rel = 0;
210 PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
217 static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * channel) {
218 struct ide_drive * drive = get_selected_drive(channel);
219 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
220 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
222 if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
223 ide_abort_command(ide, channel);
228 if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
229 PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
233 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
234 drive->transfer_index = 0;
236 channel->status.busy = 0;
237 channel->status.ready = 0;
238 channel->status.write_fault = 0;
239 channel->status.data_req = 1;
240 channel->status.error = 0;
242 drive->irq_flags.io_dir = 1;
243 drive->irq_flags.c_d = 0;
244 drive->irq_flags.rel = 0;
247 ide_raise_irq(ide, channel);
249 PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
256 static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel * channel) {
257 //struct ide_drive * drive = get_selected_drive(channel);
258 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
259 //uint32_t sector_count = (drive->sector_count == 0) ? 256 : drive->sector_count;
261 PrintError(VM_NONE, VCORE_NONE, "Extended Sector read not implemented\n");