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);
62 drive_id->dword_io = 1;
66 // PAD disable DMA capability
67 drive_id->dma_enable = 0; // 1;
70 drive_id->lba_enable = 1;
72 // Drive Capacity (28 bit LBA)
73 drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
75 // Drive Capacity (48 bit LBA)
76 drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
79 // lower byte is the maximum multiple sector size...
80 drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
83 // words 64-70, 54-58 valid
84 drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
87 // copied from CFA540A
88 // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
89 //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
90 // 0x0007 => MWDMA modes 0..2 supported - none selected
91 drive_id->buf[63] = 0x0007;
94 // PAD: Support PIO mode 0
95 drive_id->buf[64] = 0x0001; // PIO
97 // MWDMA transfer min cycle time
98 drive_id->buf[65] = 0x00b4;
99 // MWDMA transfer time recommended
100 drive_id->buf[66] = 0x00b4;
101 // minimum pio transfer time without flow control
102 drive_id->buf[67] = 0x012c;
103 // minimum pio transfer time with IORDY flow control
104 drive_id->buf[68] = 0x00b4;
106 drive_id->buf[71] = 30; // faked
107 drive_id->buf[72] = 30; // faked
109 // queue depth set to one
111 // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
112 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
115 drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
117 // No special features supported
119 // PAD: Disable ultra DMA capability
120 //drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
125 static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
126 struct ide_drive * drive = get_selected_drive(channel);
128 if (drive->hd_state.accessed == 0) {
129 drive->current_lba = 0;
130 drive->hd_state.accessed = 1;
133 PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
135 int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
138 PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
147 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
148 struct ide_drive * drive = get_selected_drive(channel);
150 if (drive->hd_state.accessed == 0) {
151 PrintError(VM_NONE,VCORE_NONE,"Reseting lba...\n");
152 drive->current_lba = 0;
153 drive->hd_state.accessed = 1;
156 PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
158 int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
161 PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
170 // Grand unified conversion for various addressing modes:
172 // CHS => 64 bit LBA (8 bit sector count)
173 // LBA28 => 64 bit LBA (8 bit sector count)
174 // LBA48 => 64 bit LBA (16 bit sector count)
175 static int ata_get_lba_and_size(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba, uint64_t *num_sects) {
176 struct ide_drive * drive = get_selected_drive(channel);
178 if (is_lba48(channel)) {
179 *num_sects = drive->lba48.sector_count;
180 *lba = drive->lba48.lba;
181 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba48: lba=%llu, num_sects=%llu\n",*lba,*num_sects);
184 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
185 *num_sects = (drive->sector_count == 0) ? 256 : drive->sector_count;
187 if (is_lba28(channel)) {
191 } __attribute__((packed)) lba_addr;
194 0-8: sector number reg (drive->lba0)
195 8-16: low cylinder reg (drive->lba1)
196 16-24: high cylinder reg (drive->lba2)
197 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num)
201 lba_addr.buf[0] = drive->lba0;
202 lba_addr.buf[1] = drive->lba1;
203 lba_addr.buf[2] = drive->lba2;
204 lba_addr.buf[3] = channel->drive_head.lba3;
206 *lba = lba_addr.addr;
208 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);
211 // we are in CHS mode....
214 (drive->cylinder * drive->num_heads +
215 channel->drive_head.head_num) * drive->num_sectors +
216 // sector number is 1 based
217 (drive->sector_num - 1);
220 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",
221 drive->cylinder, channel->drive_head.head_num, drive->sector_num,
222 drive->num_cylinders, drive->num_heads, drive->num_sectors, *lba,*num_sects );
226 if ((*lba + *num_sects) >
227 drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
228 PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%llu) (num_sects=%llu) (ReadEnd=%llu) (capacity=%llu)\n",
230 *lba + (*num_sects * HD_SECTOR_SIZE),
231 drive->ops->get_capacity(drive->private_data));
239 static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * channel) {
241 struct ide_drive * drive = get_selected_drive(channel);
243 if (ata_get_lba_and_size(ide, channel, &(drive->current_lba), §_cnt ) == -1) {
244 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
245 ide_abort_command(ide, channel);
249 PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%llu\n", drive->current_lba, sect_cnt);
251 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE ;
252 drive->transfer_index = 0;
253 channel->status.busy = 0;
254 channel->status.ready = 0;
255 channel->status.write_fault = 0;
256 channel->status.data_req = 1;
257 channel->status.error = 0;
259 PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
266 static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * channel) {
268 struct ide_drive * drive = get_selected_drive(channel);
270 if (ata_get_lba_and_size(ide, channel, &(drive->current_lba),§_cnt) == -1) {
271 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
272 ide_abort_command(ide, channel);
277 if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
278 PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
282 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
283 drive->transfer_index = 0;
285 channel->status.busy = 0;
286 channel->status.ready = 0;
287 channel->status.write_fault = 0;
288 channel->status.data_req = 1;
289 channel->status.error = 0;
291 ide_raise_irq(ide, channel);
293 PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
299 /* ATA COMMANDS as per */
300 /* ACS-2 T13/2015-D Table B.2 Command codes */
302 #define CFA_REQ_EXT_ERROR_CODE 0x03
304 #define ATA_DEVICE_RESET 0x08
305 #define ATA_RECAL 0x10
306 #define ATA_READ 0x20
307 #define ATA_READ_ONCE 0x21
308 #define ATA_READ_EXT 0x24
309 #define ATA_READDMA_EXT 0x25
310 #define ATA_READDMA_QUEUED_EXT 0x26
311 #define ATA_READ_NATIVE_MAX_EXT 0x27
312 #define ATA_MULTREAD_EXT 0x29
313 #define ATA_WRITE 0x30
314 #define ATA_WRITE_ONCE 0x31
315 #define ATA_WRITE_EXT 0x34
316 #define ATA_WRITEDMA_EXT 0x35
317 #define ATA_WRITEDMA_QUEUED_EXT 0x36
318 #define ATA_SET_MAX_EXT 0x37
319 #define ATA_SET_MAX_EXT 0x37
320 #define CFA_WRITE_SECT_WO_ERASE 0x38
321 #define ATA_MULTWRITE_EXT 0x39
322 #define ATA_WRITE_VERIFY 0x3C
323 #define ATA_VERIFY 0x40
324 #define ATA_VERIFY_ONCE 0x41
325 #define ATA_VERIFY_EXT 0x42
326 #define ATA_SEEK 0x70
327 #define CFA_TRANSLATE_SECTOR 0x87
328 #define ATA_DIAGNOSE 0x90
329 #define ATA_SPECIFY 0x91
330 #define ATA_DOWNLOAD_MICROCODE 0x92
331 #define ATA_STANDBYNOW2 0x94
332 #define ATA_IDLEIMMEDIATE2 0x95
333 #define ATA_STANDBY2 0x96
334 #define ATA_SETIDLE2 0x97
335 #define ATA_CHECKPOWERMODE2 0x98
336 #define ATA_SLEEPNOW2 0x99
337 #define ATA_PACKETCMD 0xA0
338 #define ATA_PIDENTIFY 0xA1
339 #define ATA_QUEUED_SERVICE 0xA2
340 #define ATA_SMART 0xB0
341 #define CFA_ACCESS_METADATA_STORAGE 0xB8
342 #define CFA_ERASE_SECTORS 0xC0
343 #define ATA_MULTREAD 0xC4
344 #define ATA_MULTWRITE 0xC5
345 #define ATA_SETMULT 0xC6
346 #define ATA_READDMA 0xC8
347 #define ATA_READDMA_ONCE 0xC9
348 #define ATA_WRITEDMA 0xCA
349 #define ATA_WRITEDMA_ONCE 0xCB
350 #define ATA_WRITEDMA_QUEUED 0xCC
351 #define CFA_WRITE_MULTI_WO_ERASE 0xCD
352 #define ATA_GETMEDIASTATUS 0xDA
353 #define ATA_DOORLOCK 0xDE
354 #define ATA_DOORUNLOCK 0xDF
355 #define ATA_STANDBYNOW1 0xE0
356 #define ATA_IDLEIMMEDIATE 0xE1
357 #define ATA_STANDBY 0xE2
358 #define ATA_SETIDLE1 0xE3
359 #define ATA_READ_BUFFER 0xE4
360 #define ATA_CHECKPOWERMODE1 0xE5
361 #define ATA_SLEEPNOW1 0xE6
362 #define ATA_FLUSH_CACHE 0xE7
363 #define ATA_WRITE_BUFFER 0xE8
364 #define ATA_FLUSH_CACHE_EXT 0xEA
365 #define ATA_IDENTIFY 0xEC
366 #define ATA_MEDIAEJECT 0xED
367 #define ATA_SETFEATURES 0xEF
368 #define IBM_SENSE_CONDITION 0xF0
369 #define ATA_SECURITY_SET_PASS 0xF1
370 #define ATA_SECURITY_UNLOCK 0xF2
371 #define ATA_SECURITY_ERASE_PREPARE 0xF3
372 #define ATA_SECURITY_ERASE_UNIT 0xF4
373 #define ATA_SECURITY_FREEZE_LOCK 0xF5
374 #define CFA_WEAR_LEVEL 0xF5
375 #define ATA_SECURITY_DISABLE 0xF6