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 drive_id->num_cylinders = drive->num_cylinders;
47 drive_id->num_heads = drive->num_heads;
48 drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE;
49 drive_id->bytes_per_sector = HD_SECTOR_SIZE;
50 drive_id->sectors_per_track = drive->num_sectors;
53 // These buffers do not contain a terminating "\0"
54 memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
55 memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
56 memcpy(drive_id->model_num, drive->model, 40);
59 drive_id->dword_io = 1;
63 // PAD disable DMA capability
64 drive_id->dma_enable = 0; // 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;
80 // words 64-70, 54-58 valid
81 drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
84 // copied from CFA540A
85 // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
86 //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
87 // 0x0007 => MWDMA modes 0..2 supported - none selected
88 drive_id->buf[63] = 0x0007;
91 // PAD: Support PIO mode 0
92 drive_id->buf[64] = 0x0001; // PIO
94 // MWDMA transfer min cycle time
95 drive_id->buf[65] = 0x00b4;
96 // MWDMA transfer time recommended
97 drive_id->buf[66] = 0x00b4;
98 // minimum pio transfer time without flow control
99 drive_id->buf[67] = 0x012c;
100 // minimum pio transfer time with IORDY flow control
101 drive_id->buf[68] = 0x00b4;
103 drive_id->buf[71] = 30; // faked
104 drive_id->buf[72] = 30; // faked
106 // queue depth set to one
108 // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
109 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
112 drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
114 // No special features supported
116 // PAD: Disable ultra DMA capability
117 //drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
122 static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
123 struct ide_drive * drive = get_selected_drive(channel);
125 if (drive->hd_state.accessed == 0) {
126 drive->current_lba = 0;
127 drive->hd_state.accessed = 1;
130 PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
132 int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
135 PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
144 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
145 struct ide_drive * drive = get_selected_drive(channel);
147 if (drive->hd_state.accessed == 0) {
148 PrintError(VM_NONE,VCORE_NONE,"Reseting lba...\n");
149 drive->current_lba = 0;
150 drive->hd_state.accessed = 1;
153 PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
155 int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
158 PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
167 static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba) {
168 struct ide_drive * drive = get_selected_drive(channel);
169 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
170 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
172 if (is_lba_enabled(channel)) {
176 } __attribute__((packed)) lba_addr;
179 0-8: sector number reg (drive->lba0)
180 8-16: low cylinder reg (drive->lba1)
181 16-24: high cylinder reg (drive->lba2)
182 24-28: low 4 bits of drive_head reg (channel->drive_head.head_num)
186 lba_addr.buf[0] = drive->lba0;
187 lba_addr.buf[1] = drive->lba1;
188 lba_addr.buf[2] = drive->lba2;
189 lba_addr.buf[3] = channel->drive_head.lba3;
191 *lba = lba_addr.addr;
193 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: lba0=%u (sect), lba1=%u (cyllow), lba2=%u (cylhigh), lba3=%d (head) => lba=%llu\n", drive->lba0, drive->lba1, drive->lba2, channel->drive_head.lba3, *lba);
196 // we are in CHS mode....
199 (drive->cylinder * drive->num_heads +
200 channel->drive_head.head_num) * drive->num_sectors +
201 // sector number is 1 based
202 (drive->sector_num - 1);
205 PrintDebug(VM_NONE,VCORE_NONE,"get_lba: Huh, 1995 has returned - CHS (%u,%u,%u) addressing on drive of (%u,%u,%u) translated as %llu....\n",
206 drive->cylinder, channel->drive_head.head_num, drive->sector_num,
207 drive->num_cylinders, drive->num_heads, drive->num_sectors, *lba );
210 if ((*lba + sect_cnt) >
211 drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
212 PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%llu) (sect_cnt=%u) (ReadEnd=%llu) (capacity=%llu)\n",
214 *lba + (sect_cnt * HD_SECTOR_SIZE),
215 drive->ops->get_capacity(drive->private_data));
224 static int ata_write_sectors(struct ide_internal * ide, struct ide_channel * channel) {
225 struct ide_drive * drive = get_selected_drive(channel);
226 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
228 if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
229 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba\n");
230 ide_abort_command(ide, channel);
234 PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%u\n", drive->current_lba, sect_cnt);
236 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE ;
237 drive->transfer_index = 0;
238 channel->status.busy = 0;
239 channel->status.ready = 0;
240 channel->status.write_fault = 0;
241 channel->status.data_req = 1;
242 channel->status.error = 0;
244 PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
251 static int ata_read_sectors(struct ide_internal * ide, struct ide_channel * channel) {
252 struct ide_drive * drive = get_selected_drive(channel);
253 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
254 uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
256 if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
257 PrintError(VM_NONE,VCORE_NONE,"Cannot get lba\n");
258 ide_abort_command(ide, channel);
263 if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
264 PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
268 drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
269 drive->transfer_index = 0;
271 channel->status.busy = 0;
272 channel->status.ready = 0;
273 channel->status.write_fault = 0;
274 channel->status.data_req = 1;
275 channel->status.error = 0;
277 ide_raise_irq(ide, channel);
279 PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
286 static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel * channel) {
287 //struct ide_drive * drive = get_selected_drive(channel);
288 // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
289 //uint32_t sector_count = (drive->sector_count == 0) ? 256 : drive->sector_count;
291 PrintError(VM_NONE, VCORE_NONE, "Extended Sector read not implemented\n");
296 /* ATA COMMANDS as per */
297 /* ACS-2 T13/2015-D Table B.2 Command codes */
299 #define CFA_REQ_EXT_ERROR_CODE 0x03
301 #define ATA_DEVICE_RESET 0x08
302 #define ATA_RECAL 0x10
303 #define ATA_READ 0x20
304 #define ATA_READ_ONCE 0x21
305 #define ATA_READ_EXT 0x24
306 #define ATA_READDMA_EXT 0x25
307 #define ATA_READDMA_QUEUED_EXT 0x26
308 #define ATA_READ_NATIVE_MAX_EXT 0x27
309 #define ATA_MULTREAD_EXT 0x29
310 #define ATA_WRITE 0x30
311 #define ATA_WRITE_ONCE 0x31
312 #define ATA_WRITE_EXT 0x34
313 #define ATA_WRITEDMA_EXT 0x35
314 #define ATA_WRITEDMA_QUEUED_EXT 0x36
315 #define ATA_SET_MAX_EXT 0x37
316 #define ATA_SET_MAX_EXT 0x37
317 #define CFA_WRITE_SECT_WO_ERASE 0x38
318 #define ATA_MULTWRITE_EXT 0x39
319 #define ATA_WRITE_VERIFY 0x3C
320 #define ATA_VERIFY 0x40
321 #define ATA_VERIFY_ONCE 0x41
322 #define ATA_VERIFY_EXT 0x42
323 #define ATA_SEEK 0x70
324 #define CFA_TRANSLATE_SECTOR 0x87
325 #define ATA_DIAGNOSE 0x90
326 #define ATA_SPECIFY 0x91
327 #define ATA_DOWNLOAD_MICROCODE 0x92
328 #define ATA_STANDBYNOW2 0x94
329 #define ATA_IDLEIMMEDIATE2 0x95
330 #define ATA_STANDBY2 0x96
331 #define ATA_SETIDLE2 0x97
332 #define ATA_CHECKPOWERMODE2 0x98
333 #define ATA_SLEEPNOW2 0x99
334 #define ATA_PACKETCMD 0xA0
335 #define ATA_PIDENTIFY 0xA1
336 #define ATA_QUEUED_SERVICE 0xA2
337 #define ATA_SMART 0xB0
338 #define CFA_ACCESS_METADATA_STORAGE 0xB8
339 #define CFA_ERASE_SECTORS 0xC0
340 #define ATA_MULTREAD 0xC4
341 #define ATA_MULTWRITE 0xC5
342 #define ATA_SETMULT 0xC6
343 #define ATA_READDMA 0xC8
344 #define ATA_READDMA_ONCE 0xC9
345 #define ATA_WRITEDMA 0xCA
346 #define ATA_WRITEDMA_ONCE 0xCB
347 #define ATA_WRITEDMA_QUEUED 0xCC
348 #define CFA_WRITE_MULTI_WO_ERASE 0xCD
349 #define ATA_GETMEDIASTATUS 0xDA
350 #define ATA_DOORLOCK 0xDE
351 #define ATA_DOORUNLOCK 0xDF
352 #define ATA_STANDBYNOW1 0xE0
353 #define ATA_IDLEIMMEDIATE 0xE1
354 #define ATA_STANDBY 0xE2
355 #define ATA_SETIDLE1 0xE3
356 #define ATA_READ_BUFFER 0xE4
357 #define ATA_CHECKPOWERMODE1 0xE5
358 #define ATA_SLEEPNOW1 0xE6
359 #define ATA_FLUSH_CACHE 0xE7
360 #define ATA_WRITE_BUFFER 0xE8
361 #define ATA_FLUSH_CACHE_EXT 0xEA
362 #define ATA_IDENTIFY 0xEC
363 #define ATA_MEDIAEJECT 0xED
364 #define ATA_SETFEATURES 0xEF
365 #define IBM_SENSE_CONDITION 0xF0
366 #define ATA_SECURITY_SET_PASS 0xF1
367 #define ATA_SECURITY_UNLOCK 0xF2
368 #define ATA_SECURITY_ERASE_PREPARE 0xF3
369 #define ATA_SECURITY_ERASE_UNIT 0xF4
370 #define ATA_SECURITY_FREEZE_LOCK 0xF5
371 #define CFA_WEAR_LEVEL 0xF5
372 #define ATA_SECURITY_DISABLE 0xF6