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.


0f9c8df6dfd1058dad9dbf895633962f5b488778
[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 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  ";
30
31     drive->transfer_length = 512;
32     drive->transfer_index = 0;
33
34
35     memset(drive_id->buf, 0, sizeof(drive_id->buf));
36
37     drive_id->fixed_drive = 1;
38     drive_id->removable_media = 0;
39
40     // Black magic...
41     drive_id->disk_speed1 = 1;
42     drive_id->disk_speed3 = 1;
43
44     drive_id->cdrom_flag = 0;
45
46     // Make it the simplest drive possible (1 head, 1 cyl, 1 sect/track)
47     drive_id->num_cylinders = drive->num_cylinders;
48     drive_id->num_heads = drive->num_heads;
49     drive_id->bytes_per_track = drive->num_sectors * HD_SECTOR_SIZE;
50     drive_id->bytes_per_sector = HD_SECTOR_SIZE;
51     drive_id->sectors_per_track = drive->num_sectors;
52
53
54     // These buffers do not contain a terminating "\0"
55     memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
56     memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
57     memcpy(drive_id->model_num, drive->model, 40);
58
59     // 32 bits access
60     drive_id->dword_io = 1;
61
62
63     // enable DMA access
64     drive_id->dma_enable = 1;
65
66     // enable LBA access
67     drive_id->lba_enable = 1;
68     
69     // Drive Capacity (28 bit LBA)
70     drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
71     
72     // Drive Capacity (48 bit LBA)
73     drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
74
75
76     // lower byte is the maximum multiple sector size...
77     drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
78
79
80
81     // words 64-70, 54-58 valid
82     drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
83
84
85     // copied from CFA540A
86     // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
87     //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
88     drive_id->buf[63] = 0x0007;
89
90     
91     //    drive_id->buf[64] = 0x0001; // PIO
92     drive_id->buf[65] = 0x00b4;
93     drive_id->buf[66] = 0x00b4;
94     drive_id->buf[67] = 0x012c;
95     drive_id->buf[68] = 0x00b4;
96
97     drive_id->buf[71] = 30; // faked
98     drive_id->buf[72] = 30; // faked
99
100     //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
101     drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
102
103
104     drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
105
106
107     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
108
109 }
110
111
112 static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
113     struct ide_drive * drive = get_selected_drive(channel);
114
115     if (drive->hd_state.accessed == 0) {
116         drive->current_lba = 0;
117         drive->hd_state.accessed = 1;
118     }
119
120     PrintDebug(VM_NONE, VCORE_NONE,"Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
121
122     int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
123     
124     if (ret == -1) {
125         PrintError(VM_NONE, VCORE_NONE,"IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
126         return -1;
127     }
128
129     return 0;
130 }
131
132
133
134 static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
135     struct ide_drive * drive = get_selected_drive(channel);
136
137     PrintDebug(VM_NONE, VCORE_NONE,"Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
138
139     int ret = drive->ops->write(src, 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 writing 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_get_lba(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba) {
152     struct ide_drive * drive = get_selected_drive(channel);
153     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
154     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
155
156     union {
157         uint32_t addr;
158         uint8_t buf[4];
159     } __attribute__((packed)) lba_addr;
160
161     /* LBA addr bits:
162        0-8: sector number reg  (drive->lba0)
163        8-16: low cylinder reg (drive->lba1)
164        16-24: high cylinder reg (drive->lba2)
165        24-28:  low 4 bits of drive_head reg (channel->drive_head.head_num)
166      */
167
168     lba_addr.buf[0] = drive->lba0;
169     lba_addr.buf[1] = drive->lba1;
170     lba_addr.buf[2] = drive->lba2;
171     lba_addr.buf[3] = channel->drive_head.lba3;
172
173
174     if ((lba_addr.addr + sect_cnt) > 
175         drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
176         PrintError(VM_NONE, VCORE_NONE,"IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n", 
177                    lba_addr.addr, sect_cnt, 
178                    lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE),
179                    (void *)(addr_t)(drive->ops->get_capacity(drive->private_data)));
180         return -1;
181     }
182
183     *lba = lba_addr.addr;
184     return 0;
185 }
186
187
188 // 28 bit LBA
189 static int ata_write_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
190     struct ide_drive * drive = get_selected_drive(channel);
191     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
192
193     if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
194         ide_abort_command(ide, channel);
195         return 0;
196     }
197
198     drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
199     drive->transfer_index = 0;
200     channel->status.busy = 0;
201     channel->status.ready = 0;
202     channel->status.write_fault = 0;
203     channel->status.data_req = 1;
204     channel->status.error = 0;
205
206     drive->irq_flags.io_dir = 1;
207     drive->irq_flags.c_d = 0;
208     drive->irq_flags.rel = 0;
209
210     PrintDebug(VM_NONE, VCORE_NONE, "IDE: Returning from write sectors\n");
211
212     return 0;
213 }
214
215
216 // 28 bit LBA
217 static int ata_read_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
218     struct ide_drive * drive = get_selected_drive(channel);
219     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
220     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
221
222     if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
223         ide_abort_command(ide, channel);
224         return 0;
225     }
226
227     
228     if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
229         PrintError(VM_NONE, VCORE_NONE,"Could not read disk sector\n");
230         return -1;
231     }
232
233     drive->transfer_length = sect_cnt * HD_SECTOR_SIZE;
234     drive->transfer_index = 0;
235
236     channel->status.busy = 0;
237     channel->status.ready = 0;
238     channel->status.write_fault = 0;
239     channel->status.data_req = 1;
240     channel->status.error = 0;
241
242     drive->irq_flags.io_dir = 1;
243     drive->irq_flags.c_d = 0;
244     drive->irq_flags.rel = 0;
245
246
247     ide_raise_irq(ide, channel);
248
249     PrintDebug(VM_NONE, VCORE_NONE,"Returning from read sectors\n");
250
251     return 0;
252 }
253
254
255 // 48 bit LBA
256 static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel * channel) {
257     //struct ide_drive * drive = get_selected_drive(channel);
258     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
259     //uint32_t sector_count = (drive->sector_count == 0) ? 256 : drive->sector_count;
260
261     PrintError(VM_NONE, VCORE_NONE, "Extended Sector read not implemented\n");
262
263     return -1;
264 }
265
266 #endif