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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #define ATAPI_PACKET_SIZE 12
22 #include "atapi-types.h"
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);
28 // overload error register with ATAPI value
29 channel->error_reg.val = sense_key << 4;
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;
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;
43 ide_raise_irq(dev, channel);
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;
53 ide_raise_irq(dev, channel);
58 static int atapi_read_chunk(struct vm_device * dev, struct ide_channel * channel) {
59 struct ide_drive * drive = get_selected_drive(channel);
61 int ret = drive->cd_ops->read(drive->data_buf, drive->cd_state.current_lba, drive->private_data);
64 PrintError("IDE: Error reading CD block (LBA=%x)\n", drive->cd_state.current_lba);
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);
77 /* Check if cd is ready
78 * if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
82 atapi_cmd_nop(dev, channel);
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);
90 drive->cd_state.current_lba = lba;
93 if (atapi_read_chunk(dev, channel) == -1) {
94 PrintError("IDE: Could not read initial chunk from CD\n");
98 drive->transfer_length = xfer_len;
99 drive->transfer_index = 0;
101 channel->status.busy = 0;
102 channel->status.data_req = 1;
103 channel->status.error = 0;
105 ide_raise_irq(dev, channel);
112 static void atapi_req_sense(struct vm_device * dev, struct ide_channel * channel) {
113 struct ide_drive * drive = get_selected_drive(channel);
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));
119 ide_raise_irq(dev, channel);
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];
126 PrintDebug("IDE: ATAPI Command %x\n", command);
129 case 0x00: // test unit ready
130 atapi_cmd_nop(dev, channel);
132 /* if drive not ready:
133 atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
136 case 0x03: // request sense
137 atapi_req_sense(dev, channel);
140 case 0x28: // read(10)
141 if (atapi_read10(dev, channel) == -1) {
142 PrintError("IDE: Error in ATAPI read (%x)\n", command);
147 case 0xa8: // read(12)
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
160 case 0x1e: // lock door
161 case 0x42: // read sub-channel
162 case 0x51: // read disk info
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
174 case 0xbb: // set cd speed
175 case 0x4e: // stop play/scan
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);
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 ";
194 drive->transfer_length = 512;
195 drive->transfer_index = 0;
196 memset(drive_id->buf, 0, sizeof(drive_id->buf));
198 drive_id->fixed_drive = 1;
199 drive_id->removable_media = 1;
202 drive_id->disk_speed1 = 1;
203 drive_id->disk_speed3 = 1;
205 drive_id->cdrom_flag = 1;
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);
213 drive_id->dword_io = 1;
216 drive_id->lba_enable = 1;
219 // words 64-70, 54-58 valid
220 drive_id->buf[53] = 0x0003;
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;
230 drive_id->buf[71] = 30; // faked
231 drive_id->buf[72] = 30; // faked
233 drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4