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.


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