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.


IDE/ATA enhancements: read/write multiple, lba48 addressing, cleanup
[palacios.git] / palacios / src / devices / ata.h
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifndef _DEVICES_ATA_H_
21 #define _DEVICES_ATA_H_
22
23 #define MAX_MULT_SECTORS  255
24
25
26
27
28
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  ";
33
34     drive->transfer_length = 512;
35     drive->transfer_index = 0;
36
37
38     memset(drive_id->buf, 0, sizeof(drive_id->buf));
39
40     drive_id->fixed_drive = 1;
41     drive_id->removable_media = 0;
42
43     // Black magic...
44     drive_id->disk_speed1 = 1;
45     drive_id->disk_speed3 = 1;
46
47     drive_id->cdrom_flag = 0;
48
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;
54
55
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);
60
61     // 32 bits access
62     drive_id->dword_io = 1;
63
64
65     // enable DMA access
66     // PAD disable DMA capability
67     drive_id->dma_enable = 0; // 1;
68
69     // enable LBA access
70     drive_id->lba_enable = 1;
71     
72     // Drive Capacity (28 bit LBA)
73     drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
74     
75     // Drive Capacity (48 bit LBA)
76     drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
77
78
79     // lower byte is the maximum multiple sector size...
80     drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
81
82
83     // words 64-70, 54-58 valid
84     drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
85
86
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;
92
93     
94     // PAD: Support PIO mode 0
95     drive_id->buf[64] = 0x0001; // PIO
96
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;
105
106     drive_id->buf[71] = 30; // faked
107     drive_id->buf[72] = 30; // faked
108
109     // queue depth set to one
110
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
113
114
115     drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
116
117     // No special features supported
118
119     // PAD: Disable ultra DMA capability
120     //drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
121
122 }
123
124
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);
127
128     if (drive->hd_state.accessed == 0) {
129         drive->current_lba = 0;
130         drive->hd_state.accessed = 1;
131     }
132
133     PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
134
135     int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
136     
137     if (ret == -1) {
138         PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
139         return -1;
140     }
141
142     return 0;
143 }
144
145
146
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);
149
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;
154     }
155
156     PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
157
158     int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
159
160     if (ret == -1) {
161         PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
162         return -1;
163     }
164
165     return 0;
166 }
167
168
169 //
170 // Grand unified conversion for various addressing modes:
171 //
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);
177
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);
182     } else {
183         // LBA48 or CHS
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;
186         
187         if (is_lba28(channel)) { 
188             union {
189                 uint32_t addr;
190                 uint8_t buf[4];
191             } __attribute__((packed)) lba_addr;
192             
193             /* LBA addr bits:
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)
198             */
199             
200             
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;
205             
206             *lba = lba_addr.addr;
207             
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);
209             
210         } else {
211             // we are in CHS mode....
212             
213             *lba = 
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);
218             
219             
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 );
223         }
224     }
225         
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", 
229                    *lba, *num_sects, 
230                    *lba + (*num_sects * HD_SECTOR_SIZE),
231                    drive->ops->get_capacity(drive->private_data));
232         return -1;
233     }
234     
235     return 0;
236 }
237
238
239 static int ata_write_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
240     uint64_t sect_cnt;
241     struct ide_drive * drive = get_selected_drive(channel);
242
243     if (ata_get_lba_and_size(ide, channel, &(drive->current_lba), &sect_cnt ) == -1) {
244         PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
245         ide_abort_command(ide, channel);
246         return 0;
247     }
248
249     PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%llu\n", drive->current_lba, sect_cnt);
250
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;
258
259     PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
260
261     return 0;
262 }
263
264
265 // 28 bit LBA or CHS
266 static int ata_read_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
267     uint64_t sect_cnt;
268     struct ide_drive * drive = get_selected_drive(channel);
269
270     if (ata_get_lba_and_size(ide, channel, &(drive->current_lba),&sect_cnt) == -1) {
271         PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
272         ide_abort_command(ide, channel);
273         return 0;
274     }
275
276     
277     if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
278         PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
279         return -1;
280     }
281
282     drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
283     drive->transfer_index = 0;
284
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;
290
291     ide_raise_irq(ide, channel);
292
293     PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
294
295     return 0;
296 }
297
298
299 /* ATA COMMANDS as per */
300 /* ACS-2 T13/2015-D Table B.2 Command codes */
301 #define ATA_NOP                         0x00
302 #define CFA_REQ_EXT_ERROR_CODE          0x03 
303 #define ATA_DSM                         0x06
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
376
377 #endif