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.


Cleanup and sanity-checking of unintentional integer overflow, unsigned/zero comparis...
[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 for PIO supported
62     drive_id->dword_io = 1;
63
64
65     // enable DMA access
66     // We want guest to assume UDMA5
67     // but any DMA model looks the same to the guest
68     drive_id->dma_enable = 1; 
69
70     // enable LBA access
71     drive_id->lba_enable = 1;
72     
73     // Drive Capacity (28 bit LBA)
74     drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
75     
76     // Drive Capacity (48 bit LBA)
77     drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
78
79
80     // lower byte is the maximum multiple sector size...
81     drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
82
83
84     // words 64-70, 54-58 valid
85     drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
86
87
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;
93
94     
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
99
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;
108
109     drive_id->buf[71] = 30; // faked
110     drive_id->buf[72] = 30; // faked
111
112     // queue depth set to one
113     // We should not expect queued DMAs
114
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
117
118
119     drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
120
121     // No special features supported
122
123     // Pretend drive is already autoconfed to UDMA5
124     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
125
126 }
127
128
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);
131
132     if (drive->hd_state.accessed == 0) {
133         drive->current_lba = 0;
134         drive->hd_state.accessed = 1;
135     }
136
137     PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
138
139     int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
140     
141     if (ret == -1) {
142         PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
143         return -1;
144     }
145
146     return 0;
147 }
148
149
150
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);
153
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;
158     }
159
160     PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
161
162     int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
163
164     if (ret == -1) {
165         PrintError(VM_NONE, VCORE_NONE,"IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
166         return -1;
167     }
168
169     return 0;
170 }
171
172
173 //
174 // Grand unified conversion for various addressing modes:
175 //
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);
181
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);
186     } else {
187         // LBA48 or CHS
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;
190         
191         if (is_lba28(channel)) { 
192             union {
193                 uint32_t addr;
194                 uint8_t buf[4];
195             } __attribute__((packed)) lba_addr;
196             
197             /* LBA addr bits:
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)
202             */
203             
204             
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;
209             
210             *lba = lba_addr.addr;
211             
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);
213             
214         } else {
215             // we are in CHS mode....
216             
217             *lba = 
218                 ((uint64_t)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);
222             
223             
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 );
227         }
228     }
229         
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", 
233                    *lba, *num_sects, 
234                    *lba + (*num_sects * HD_SECTOR_SIZE),
235                    drive->ops->get_capacity(drive->private_data));
236         return -1;
237     }
238     
239     return 0;
240 }
241
242
243 static int ata_write_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
244     uint64_t sect_cnt;
245     struct ide_drive * drive = get_selected_drive(channel);
246
247     if (ata_get_lba_and_size(ide, channel, &(drive->current_lba), &sect_cnt ) == -1) {
248         PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
249         ide_abort_command(ide, channel);
250         return 0;
251     }
252
253     PrintDebug(VM_NONE,VCORE_NONE,"ata write sectors: lba=%llu sect_cnt=%llu\n", drive->current_lba, sect_cnt);
254
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;
262
263     PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
264
265     return 0;
266 }
267
268
269 // 28 bit LBA or CHS
270 static int ata_read_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
271     uint64_t sect_cnt;
272     struct ide_drive * drive = get_selected_drive(channel);
273
274     if (ata_get_lba_and_size(ide, channel, &(drive->current_lba),&sect_cnt) == -1) {
275         PrintError(VM_NONE,VCORE_NONE,"Cannot get lba+size\n");
276         ide_abort_command(ide, channel);
277         return 0;
278     }
279
280     
281     if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
282         PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
283         return -1;
284     }
285
286     drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
287     drive->transfer_index = 0;
288
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;
294
295     ide_raise_irq(ide, channel);
296
297     PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
298
299     return 0;
300 }
301
302
303 /* ATA COMMANDS as per */
304 /* ACS-2 T13/2015-D Table B.2 Command codes */
305 #define ATA_NOP                         0x00
306 #define CFA_REQ_EXT_ERROR_CODE          0x03 
307 #define ATA_DSM                         0x06
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
380
381 #endif