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
29 static void ata_identify_device(struct ide_drive * drive) {
30 struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
31 const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
32 const char* firmware = "ALPHA1 ";
34 drive->transfer_length = 512;
35 drive->transfer_index = 0;
38 memset(drive_id->buf, 0, sizeof(drive_id->buf));
40 drive_id->fixed_drive = 1;
41 drive_id->removable_media = 0;
44 drive_id->disk_speed1 = 1;
45 drive_id->disk_speed3 = 1;
47 drive_id->cdrom_flag = 0;
49 drive_id->num_cylinders = drive->num_cylinders;
50 drive_id->num_heads = drive->num_heads;
51 drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE;
52 drive_id->bytes_per_sector = HD_SECTOR_SIZE;
53 drive_id->sectors_per_track = drive->num_sectors;
56 // These buffers do not contain a terminating "\0"
57 memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
58 memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
59 memcpy(drive_id->model_num, drive->model, 40);
61 // 32 bits access for PIO supported
62 drive_id->dword_io = 1;
66 // We want guest to assume UDMA5
67 // but any DMA model looks the same to the guest
68 drive_id->dma_enable = 1;
71 drive_id->lba_enable = 1;
73 // Drive Capacity (28 bit LBA)
74 drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
76 // Drive Capacity (48 bit LBA)
77 drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
80 // lower byte is the maximum multiple sector size...
81 drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
84 // words 64-70, 54-58 valid
85 drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
88 // copied from CFA540A
89 // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
90 //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
91 // 0x0007 => MWDMA modes 0..2 supported - none selected
92 drive_id->buf[63] = 0x0007;
95 // We wll support PIO mode 0
96 // Maybe revisit this later to allow advanced modes
97 // We really want the guest to use DMA
98 drive_id->buf[64] = 0x0001; // PIO
100 // MWDMA transfer min cycle time
101 drive_id->buf[65] = 0x00b4;
102 // MWDMA transfer time recommended
103 drive_id->buf[66] = 0x00b4;
104 // minimum pio transfer time without flow control
105 drive_id->buf[67] = 0x012c;
106 // minimum pio transfer time with IORDY flow control
107 drive_id->buf[68] = 0x00b4;
109 drive_id->buf[71] = 30; // faked
110 drive_id->buf[72] = 30; // faked
112 // queue depth set to one
113 // We should not expect queued DMAs
115 // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
116 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
119 drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
121 // No special features supported
123 // Pretend drive is already autoconfed to UDMA5
124 drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
129 static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
130 struct ide_drive * drive = get_selected_drive(channel);
132 if (drive->hd_state.accessed == 0) {
133 drive->current_lba = 0;
134 drive->hd_state.accessed = 1;
137 PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
139 int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
142 PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
151 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
152 struct ide_drive * drive = get_selected_drive(channel);
154 if (drive->hd_state.accessed == 0) {
155 PrintError(VM_NONE,VCORE_NONE,"Reseting lba...\n");
156 drive->current_lba = 0;
157 drive->hd_state.accessed = 1;
160 PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
162 int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
165 PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
174 // Grand unified conversion for various addressing modes:
176 // CHS => 64 bit LBA (8 bit sector count)
177 // LBA28 => 64 bit LBA (8 bit sector count)
178 // LBA48 => 64 bit LBA (16 bit sector count)
179 static int ata_get_lba_and_size(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba, uint64_t *num_sects) {
180 struct ide_drive * drive = get_selected_drive(channel);
182 if (is_lba48(channel)) {
183 *num_sects = drive->lba48.sector_count;
184 *lba = drive->lba48.lba;
185 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba48: lba=%llu, num_sects=%llu\n",*lba,*num_sects);
188 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
189 *num_sects = (drive->sector_count == 0) ? 256 : drive->sector_count;
191 if (is_lba28(channel)) {
195 } __attribute__((packed)) lba_addr;
198 0-8: sector number reg (drive->lba0)
199 8-16: low cylinder reg (drive->lba1)
200 16-24: high cylinder reg (drive->lba2)
201 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num)
205 lba_addr.buf[0] = drive->lba0;
206 lba_addr.buf[1] = drive->lba1;
207 lba_addr.buf[2] = drive->lba2;
208 lba_addr.buf[3] = channel->drive_head.lba3;
210 *lba = lba_addr.addr;
212 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba28: lba0=%u (sect), lba1=%u (cyllow), lba2=%u (cylhigh), lba3=%d (head) => lba=%llu numsects=%llu\n", drive->lba0, drive->lba1, drive->lba2, channel->drive_head.lba3, *lba, *num_sects);
215 // we are in CHS mode....
218 (drive->cylinder * drive->num_heads +
219 channel->drive_head.head_num) * drive->num_sectors +
220 // sector number is 1 based
221 (drive->sector_num - 1);
224 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: Huh, 1995 has returned - CHS (%u,%u,%u) addressing on drive of (%u,%u,%u) translated as lba=%llu num_sects=%llu....\n",
225 drive->cylinder, channel->drive_head.head_num, drive->sector_num,
226 drive->num_cylinders, drive->num_heads, drive->num_sectors, *lba,*num_sects );
230 if ((*lba + *num_sects) >
231 drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
232 PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%llu) (num_sects=%llu) (ReadEnd=%llu) (capacity=%llu)\n",
234 *lba + (*num_sects * HD_SECTOR_SIZE),
235 drive->ops->get_capacity(drive->private_data));
243 static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * channel) {
245 struct ide_drive * drive = get_selected_drive(channel);
247 if (ata_get_lba_and_size(ide, channel, &(drive->current_lba), §_cnt ) == -1) {
248 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
249 ide_abort_command(ide, channel);
253 PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%llu\n", drive->current_lba, sect_cnt);
255 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE ;
256 drive->transfer_index = 0;
257 channel->status.busy = 0;
258 channel->status.ready = 0;
259 channel->status.write_fault = 0;
260 channel->status.data_req = 1;
261 channel->status.error = 0;
263 PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
270 static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * channel) {
272 struct ide_drive * drive = get_selected_drive(channel);
274 if (ata_get_lba_and_size(ide, channel, &(drive->current_lba),§_cnt) == -1) {
275 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
276 ide_abort_command(ide, channel);
281 if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
282 PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
286 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
287 drive->transfer_index = 0;
289 channel->status.busy = 0;
290 channel->status.ready = 0;
291 channel->status.write_fault = 0;
292 channel->status.data_req = 1;
293 channel->status.error = 0;
295 ide_raise_irq(ide, channel);
297 PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
303 /* ATA COMMANDS as per */
304 /* ACS-2 T13/2015-D Table B.2 Command codes */
306 #define CFA_REQ_EXT_ERROR_CODE 0x03
308 #define ATA_DEVICE_RESET 0x08
309 #define ATA_RECAL 0x10
310 #define ATA_READ 0x20
311 #define ATA_READ_ONCE 0x21
312 #define ATA_READ_EXT 0x24
313 #define ATA_READDMA_EXT 0x25
314 #define ATA_READDMA_QUEUED_EXT 0x26
315 #define ATA_READ_NATIVE_MAX_EXT 0x27
316 #define ATA_MULTREAD_EXT 0x29
317 #define ATA_WRITE 0x30
318 #define ATA_WRITE_ONCE 0x31
319 #define ATA_WRITE_EXT 0x34
320 #define ATA_WRITEDMA_EXT 0x35
321 #define ATA_WRITEDMA_QUEUED_EXT 0x36
322 #define ATA_SET_MAX_EXT 0x37
323 #define ATA_SET_MAX_EXT 0x37
324 #define CFA_WRITE_SECT_WO_ERASE 0x38
325 #define ATA_MULTWRITE_EXT 0x39
326 #define ATA_WRITE_VERIFY 0x3C
327 #define ATA_VERIFY 0x40
328 #define ATA_VERIFY_ONCE 0x41
329 #define ATA_VERIFY_EXT 0x42
330 #define ATA_SEEK 0x70
331 #define CFA_TRANSLATE_SECTOR 0x87
332 #define ATA_DIAGNOSE 0x90
333 #define ATA_SPECIFY 0x91
334 #define ATA_DOWNLOAD_MICROCODE 0x92
335 #define ATA_STANDBYNOW2 0x94
336 #define ATA_IDLEIMMEDIATE2 0x95
337 #define ATA_STANDBY2 0x96
338 #define ATA_SETIDLE2 0x97
339 #define ATA_CHECKPOWERMODE2 0x98
340 #define ATA_SLEEPNOW2 0x99
341 #define ATA_PACKETCMD 0xA0
342 #define ATA_PIDENTIFY 0xA1
343 #define ATA_QUEUED_SERVICE 0xA2
344 #define ATA_SMART 0xB0
345 #define CFA_ACCESS_METADATA_STORAGE 0xB8
346 #define CFA_ERASE_SECTORS 0xC0
347 #define ATA_MULTREAD 0xC4
348 #define ATA_MULTWRITE 0xC5
349 #define ATA_SETMULT 0xC6
350 #define ATA_READDMA 0xC8
351 #define ATA_READDMA_ONCE 0xC9
352 #define ATA_WRITEDMA 0xCA
353 #define ATA_WRITEDMA_ONCE 0xCB
354 #define ATA_WRITEDMA_QUEUED 0xCC
355 #define CFA_WRITE_MULTI_WO_ERASE 0xCD
356 #define ATA_GETMEDIASTATUS 0xDA
357 #define ATA_DOORLOCK 0xDE
358 #define ATA_DOORUNLOCK 0xDF
359 #define ATA_STANDBYNOW1 0xE0
360 #define ATA_IDLEIMMEDIATE 0xE1
361 #define ATA_STANDBY 0xE2
362 #define ATA_SETIDLE1 0xE3
363 #define ATA_READ_BUFFER 0xE4
364 #define ATA_CHECKPOWERMODE1 0xE5
365 #define ATA_SLEEPNOW1 0xE6
366 #define ATA_FLUSH_CACHE 0xE7
367 #define ATA_WRITE_BUFFER 0xE8
368 #define ATA_FLUSH_CACHE_EXT 0xEA
369 #define ATA_IDENTIFY 0xEC
370 #define ATA_MEDIAEJECT 0xED
371 #define ATA_SETFEATURES 0xEF
372 #define IBM_SENSE_CONDITION 0xF0
373 #define ATA_SECURITY_SET_PASS 0xF1
374 #define ATA_SECURITY_UNLOCK 0xF2
375 #define ATA_SECURITY_ERASE_PREPARE 0xF3
376 #define ATA_SECURITY_ERASE_UNIT 0xF4
377 #define ATA_SECURITY_FREEZE_LOCK 0xF5
378 #define CFA_WEAR_LEVEL 0xF5
379 #define ATA_SECURITY_DISABLE 0xF6