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.


added atapi handlers
[palacios.git] / palacios / src / devices / atapi.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 ATAPI_PACKET_SIZE 12
21
22 #include "atapi-types.h"
23
24 static void atapi_cmd_error(struct vm_device * dev, struct ide_channel * channel, 
25                      atapi_sense_key_t  sense_key, atapi_add_sense_code_t asc) {
26     struct ide_drive * drive = get_selected_drive(channel);
27
28     // overload error register with ATAPI value
29     channel->error_reg.val = sense_key << 4;
30     
31     channel->status.busy = 0;
32     channel->status.ready = 1;
33     channel->status.write_fault = 0;
34     channel->status.data_req = 0;
35     channel->status.error = 1;
36   
37     drive->cd_state.sense.header = 0xf0;
38     drive->cd_state.sense.rsvd1 = 0x00;
39     drive->cd_state.sense.read_len = 0x0a;
40     drive->cd_state.sense.sense_key = sense_key;
41     drive->cd_state.sense.asc = asc;
42
43     ide_raise_irq(dev, channel);
44 }
45
46
47 static void atapi_cmd_nop(struct vm_device * dev, struct ide_channel * channel) {
48     channel->status.busy = 0;
49     channel->status.ready = 1;
50     channel->status.data_req = 0;
51     channel->status.error = 0;
52
53     ide_raise_irq(dev, channel);
54 }
55
56
57
58 static int atapi_read_chunk(struct vm_device * dev, struct ide_channel * channel) {
59     struct ide_drive * drive = get_selected_drive(channel);
60
61     int ret = drive->cd_ops->read(drive->data_buf, drive->cd_state.current_lba, drive->private_data);
62
63     if (ret == -1) {
64         PrintError("IDE: Error reading CD block (LBA=%x)\n", drive->cd_state.current_lba);
65         return -1;
66     }
67
68     return 0;
69 }
70
71 static int atapi_read10(struct vm_device * dev, struct ide_channel * channel) {
72     struct ide_drive * drive = get_selected_drive(channel);
73     struct atapi_read10_cmd * cmd = (struct atapi_read10_cmd *)(drive->data_buf);
74     uint32_t lba =  be_to_le_32(cmd->lba);
75     uint16_t xfer_len = be_to_le_16(cmd->xfer_len);
76     
77     /* Check if cd is ready
78      * if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
79      */
80
81     if (xfer_len == 0) {
82         atapi_cmd_nop(dev, channel);
83         return 0;
84     }
85         
86     if ((lba + xfer_len) > drive->cd_ops->get_capacity(drive->private_data)) {
87         atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
88     }
89
90     drive->cd_state.current_lba = lba;
91
92
93     if (atapi_read_chunk(dev, channel) == -1) {
94         PrintError("IDE: Could not read initial chunk from CD\n");
95         return -1;
96     }
97     
98     drive->transfer_length = xfer_len;
99     drive->transfer_index = 0;
100
101     channel->status.busy = 0;
102     channel->status.data_req = 1;
103     channel->status.error = 0;
104
105     ide_raise_irq(dev, channel);
106
107     return 0;
108 }
109
110
111
112 static void atapi_req_sense(struct vm_device * dev, struct ide_channel * channel) {
113     struct ide_drive * drive = get_selected_drive(channel);
114
115     drive->transfer_length = 18;
116     drive->transfer_index = 0;
117     memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
118    
119     ide_raise_irq(dev, channel);
120 }
121
122 static int atapi_handle_packet(struct vm_device * dev, struct ide_channel * channel) {
123    struct ide_drive * drive = get_selected_drive(channel);
124    uint8_t command = drive->data_buf[0];
125
126    PrintDebug("IDE: ATAPI Command %x\n", command);
127
128    switch (command) {
129        case 0x00: // test unit ready
130            atapi_cmd_nop(dev, channel);
131
132            /* if drive not ready: 
133               atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
134            */
135            break;
136        case 0x03: // request sense
137            atapi_req_sense(dev, channel);
138            break;
139
140        case 0x28: // read(10)
141            if (atapi_read10(dev, channel) == -1) {
142                PrintError("IDE: Error in ATAPI read (%x)\n", command);
143                return -1;
144            }
145
146            break;
147        case 0xa8: // read(12)
148
149
150        case 0x1b: // start/stop drive
151        case 0xbd: // mechanism status 
152        case 0x5a: // mode sense
153        case 0x12: // inquiry
154        case 0x25: // read cdrom capacity
155        case 0xbe: // read cd
156        case 0x43: // read TOC
157
158
159        case 0x2b: // seek
160        case 0x1e: // lock door
161        case 0x42: // read sub-channel
162        case 0x51: // read disk info
163
164            
165        case 0x55: // mode select
166        case 0xa6: // load/unload cd
167        case 0x4b: // pause/resume
168        case 0x45: // play audio
169        case 0x47: // play audio msf
170        case 0xbc: // play cd
171        case 0xb9: // read cd msf
172        case 0x44: // read header
173        case 0xba: // scan
174        case 0xbb: // set cd speed
175        case 0x4e: // stop play/scan
176        case 0x46: // ???
177        case 0x4a: // ???
178        default:
179            PrintError("Unhandled ATAPI command %x\n", command);
180            atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
181            ide_raise_irq(dev, channel);
182            return -1;
183    }
184    
185    return 0;
186 }
187
188
189 static void atapi_identify_device(struct ide_drive * drive) {
190     struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
191     const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
192     const char* firmware = "ALPHA1  ";
193
194     drive->transfer_length = 512;
195     drive->transfer_index = 0;
196     memset(drive_id->buf, 0, sizeof(drive_id->buf));
197
198     drive_id->fixed_drive = 1;
199     drive_id->removable_media = 1;
200
201     // Black magic...
202     drive_id->disk_speed1 = 1;
203     drive_id->disk_speed3 = 1;
204
205     drive_id->cdrom_flag = 1;
206
207     // These buffers do not contain a terminating "\0"
208     memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
209     memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
210     memcpy(drive_id->model_num, drive->model, 40);
211
212     // 32 bits access
213     drive_id->dword_io = 1;
214
215     // enable LBA access
216     drive_id->lba_enable = 1;
217     
218
219     // words 64-70, 54-58 valid
220     drive_id->buf[53] = 0x0003;
221
222     // copied from CFA540A
223     drive_id->buf[63] = 0x0103; // variable (DMA stuff)
224     drive_id->buf[64] = 0x0001; // PIO
225     drive_id->buf[65] = 0x00b4;
226     drive_id->buf[66] = 0x00b4;
227     drive_id->buf[67] = 0x012c;
228     drive_id->buf[68] = 0x00b4;
229
230     drive_id->buf[71] = 30; // faked
231     drive_id->buf[72] = 30; // faked
232
233     drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
234 }