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 #ifndef __DEVICES_ATAPI_H__
21 #define __DEVICES_ATAPI_H__
23 #define ATAPI_PACKET_SIZE 12
25 #include "atapi-types.h"
28 /* ACS-2 T13/2015-D Table B.2 Command codes */
29 #define ATAPI_NOP 0x00
30 #define CFA_REQ_EXT_ERROR_CODE 0x03
31 #define ATAPI_DSM 0x06
32 #define ATAPI_DEVICE_RESET 0x08
33 #define ATAPI_RECAL 0x10
34 #define ATAPI_READ 0x20
35 #define ATAPI_READ_ONCE 0x21
36 #define ATAPI_READ_EXT 0x24
37 #define ATAPI_READDMA_EXT 0x25
38 #define ATAPI_READDMA_QUEUED_EXT 0x26
39 #define ATAPI_READ_NATIVE_MAX_EXT 0x27
40 #define ATAPI_MULTREAD_EXT 0x29
41 #define ATAPI_WRITE 0x30
42 #define ATAPI_WRITE_ONCE 0x31
43 #define ATAPI_WRITE_EXT 0x34
44 #define ATAPI_WRITEDMA_EXT 0x35
45 #define ATAPI_WRITEDMA_QUEUED_EXT 0x36
46 #define ATAPI_SET_MAX_EXT 0x37
47 #define ATAPI_SET_MAX_EXT 0x37
48 #define CFA_WRITE_SECT_WO_ERASE 0x38
49 #define ATAPI_MULTWRITE_EXT 0x39
50 #define ATAPI_WRITE_VERIFY 0x3C
51 #define ATAPI_VERIFY 0x40
52 #define ATAPI_VERIFY_ONCE 0x41
53 #define ATAPI_VERIFY_EXT 0x42
54 #define ATAPI_SEEK 0x70
55 #define CFA_TRANSLATE_SECTOR 0x87
56 #define ATAPI_DIAGNOSE 0x90
57 #define ATAPI_SPECIFY 0x91
58 #define ATAPI_DOWNLOAD_MICROCODE 0x92
59 #define ATAPI_STANDBYNOW2 0x94
60 #define ATAPI_IDLEIMMEDIATE2 0x95
61 #define ATAPI_STANDBY2 0x96
62 #define ATAPI_SETIDLE2 0x97
63 #define ATAPI_CHECKPOWERMODE2 0x98
64 #define ATAPI_SLEEPNOW2 0x99
65 #define ATAPI_PACKETCMD 0xA0
66 #define ATAPI_PIDENTIFY 0xA1
67 #define ATAPI_QUEUED_SERVICE 0xA2
68 #define ATAPI_SMART 0xB0
69 #define CFA_ACCESS_METADATA_STORAGE 0xB8
70 #define CFA_ERASE_SECTORS 0xC0
71 #define ATAPI_MULTREAD 0xC4
72 #define ATAPI_MULTWRITE 0xC5
73 #define ATAPI_SETMULT 0xC6
74 #define ATAPI_READDMA 0xC8
75 #define ATAPI_READDMA_ONCE 0xC9
76 #define ATAPI_WRITEDMA 0xCA
77 #define ATAPI_WRITEDMA_ONCE 0xCB
78 #define ATAPI_WRITEDMA_QUEUED 0xCC
79 #define CFA_WRITE_MULTI_WO_ERASE 0xCD
80 #define ATAPI_GETMEDIASTATUS 0xDA
81 #define ATAPI_DOORLOCK 0xDE
82 #define ATAPI_DOORUNLOCK 0xDF
83 #define ATAPI_STANDBYNOW1 0xE0
84 #define ATAPI_IDLEIMMEDIATE 0xE1
85 #define ATAPI_STANDBY 0xE2
86 #define ATAPI_SETIDLE1 0xE3
87 #define ATAPI_READ_BUFFER 0xE4
88 #define ATAPI_CHECKPOWERMODE1 0xE5
89 #define ATAPI_SLEEPNOW1 0xE6
90 #define ATAPI_FLUSH_CACHE 0xE7
91 #define ATAPI_WRITE_BUFFER 0xE8
92 #define ATAPI_FLUSH_CACHE_EXT 0xEA
93 #define ATAPI_IDENTIFY 0xEC
94 #define ATAPI_MEDIAEJECT 0xED
95 #define ATAPI_SETFEATURES 0xEF
96 #define IBM_SENSE_CONDITION 0xF0
97 #define ATAPI_SECURITY_SET_PASS 0xF1
98 #define ATAPI_SECURITY_UNLOCK 0xF2
99 #define ATAPI_SECURITY_ERASE_PREPARE 0xF3
100 #define ATAPI_SECURITY_ERASE_UNIT 0xF4
101 #define ATAPI_SECURITY_FREEZE_LOCK 0xF5
102 #define CFA_WEAR_LEVEL 0xF5
103 #define ATAPI_SECURITY_DISABLE 0xF6
106 * The OS will write to the cylinder register the number of bytes it wants to read
107 * however the device can change that value
110 static int atapi_update_req_len(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
111 struct ide_drive * drive = get_selected_drive(channel);
113 //PrintDebug("\tUpdating request length (pre=%d)\n", drive->req_len);
115 if (drive->req_len == 0) {
116 PrintError(VM_NONE,VCORE_NONE, "ATAPI Error: request of length 0\n");
121 channel->status.busy = 0;
122 channel->status.data_req = 1;
123 channel->status.error = 0;
125 drive->irq_flags.io_dir = 1;
126 drive->irq_flags.c_d = 0;
129 if (drive->req_len % 2) {
133 // if the device can't return as much as the OS requested
134 // this is actually a decrement of the req_len by the amount requested by the OS
135 if (drive->req_len > xfer_len) {
136 drive->req_len = xfer_len;
139 // PrintDebug("\tUpdating request length (post=%d)\n", drive->req_len);
146 // This is for simple commands that don't need to sanity check the req_len
147 static void atapi_setup_cmd_resp(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
148 struct ide_drive * drive = get_selected_drive(channel);
150 drive->transfer_length = xfer_len;
151 drive->transfer_index = 0;
152 drive->req_len = drive->transfer_length;
154 drive->irq_flags.io_dir = 1;
155 drive->irq_flags.c_d = 0;
157 channel->status.busy = 0;
158 channel->status.error = 0;
160 if (drive->transfer_length > 0) {
161 channel->status.data_req = 1;
164 ide_raise_irq(ide, channel);
167 static void atapi_cmd_error(struct ide_internal * ide, struct ide_channel * channel,
168 atapi_sense_key_t sense_key, atapi_add_sense_code_t asc) {
169 struct ide_drive * drive = get_selected_drive(channel);
171 // overload error register with ATAPI value
172 channel->error_reg.val = sense_key << 4;
174 channel->status.busy = 0;
175 channel->status.ready = 1;
176 channel->status.write_fault = 0;
177 channel->status.data_req = 0;
178 channel->status.error = 1;
180 drive->cd_state.sense.header = 0xf0;
181 drive->cd_state.sense.rsvd1 = 0x00;
182 drive->cd_state.sense.read_len = 0x0a;
183 drive->cd_state.sense.sense_key = sense_key;
184 drive->cd_state.sense.asc = asc;
187 drive->irq_flags.io_dir = 1;
188 drive->irq_flags.c_d = 1;
189 drive->irq_flags.rel = 0;
191 ide_raise_irq(ide, channel);
195 static void atapi_cmd_nop(struct ide_internal * ide, struct ide_channel * channel) {
196 struct ide_drive * drive = get_selected_drive(channel);
198 channel->status.busy = 0;
199 channel->status.ready = 1;
200 channel->status.data_req = 0;
201 channel->status.error = 0;
203 drive->irq_flags.io_dir = 1;
204 drive->irq_flags.c_d = 1;
205 drive->irq_flags.rel = 0;
207 ide_raise_irq(ide, channel);
212 static int atapi_read_chunk(struct ide_internal * ide, struct ide_channel * channel) {
213 struct ide_drive * drive = get_selected_drive(channel);
215 int ret = drive->ops->read(drive->data_buf,
216 drive->current_lba * ATAPI_BLOCK_SIZE,
217 ATAPI_BLOCK_SIZE, drive->private_data);
220 PrintError(VM_NONE,VCORE_NONE, "IDE: Error reading CD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
228 static int atapi_update_data_buf(struct ide_internal * ide, struct ide_channel * channel) {
229 struct ide_drive * drive = get_selected_drive(channel);
231 switch (drive->cd_state.atapi_cmd) {
232 case 0x28: // read(10)
233 case 0xa8: // read(12)
235 // Update lba address to point to next block
236 drive->current_lba++;
238 // read the next block
239 return atapi_read_chunk(ide, channel);
242 PrintError(VM_NONE,VCORE_NONE, "Unhandled ATAPI command in update buffer %x\n", drive->cd_state.atapi_cmd);
249 static int atapi_read10(struct guest_info * core,
250 struct ide_internal * ide,
251 struct ide_channel * channel) {
252 struct ide_drive * drive = get_selected_drive(channel);
253 struct atapi_read10_cmd * cmd = (struct atapi_read10_cmd *)(drive->data_buf);
254 uint32_t lba = be_to_le_32(cmd->lba);
255 uint16_t xfer_len = be_to_le_16(cmd->xfer_len);
257 PrintDebug(core->vm_info, core, "READ10: XferLen=%d ; LBA=%x \n", xfer_len, lba );
259 /* Check if cd is ready
260 * if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
264 atapi_cmd_nop(ide, channel);
268 if ((lba + xfer_len) > (drive->ops->get_capacity(drive->private_data) / ATAPI_BLOCK_SIZE)) {
269 PrintError(core->vm_info, core, "IDE: xfer len exceeded capacity (lba=%d) (xfer_len=%d) (ReadEnd=%d) (capacity=%d)\n",
270 lba, xfer_len, lba + xfer_len,
271 (uint32_t)drive->ops->get_capacity(drive->private_data));
272 atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
273 ide_raise_irq(ide, channel);
277 // PrintDebug(core->vm_info, core, "Reading %d blocks from LBA 0x%x\n", xfer_len, lba);
278 drive->current_lba = lba;
280 // Update the request length value in the cylinder registers
281 drive->transfer_length = xfer_len * ATAPI_BLOCK_SIZE;
282 drive->transfer_index = 0;
284 if (channel->features.dma) {
286 if (channel->dma_status.active == 1) {
287 if (dma_read(core, ide, channel) == -1) {
288 PrintError(core->vm_info, core, "Error in DMA read for CD Read10 command\n");
295 if (atapi_read_chunk(ide, channel) == -1) {
296 PrintError(core->vm_info, core, "IDE: Could not read initial chunk from CD\n");
300 // Length of ATAPI buffer sits in cylinder registers
301 // This is weird... The host sets this value to say what it would like to transfer,
302 // if it is larger than the correct size, the device shrinks it to the correct size
303 if (atapi_update_req_len(ide, channel, ATAPI_BLOCK_SIZE) == -1) {
304 PrintError(core->vm_info, core, "Could not update initial request length\n");
308 ide_raise_irq(ide, channel);
315 static void atapi_req_sense(struct ide_internal * ide, struct ide_channel * channel) {
316 struct ide_drive * drive = get_selected_drive(channel);
318 memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
320 atapi_setup_cmd_resp(ide, channel, 18);
325 static int atapi_get_capacity(struct ide_internal * ide, struct ide_channel * channel) {
326 struct ide_drive * drive = get_selected_drive(channel);
327 struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
328 uint32_t capacity = drive->ops->get_capacity(drive->private_data);
330 resp->lba = le_to_be_32((capacity / ATAPI_BLOCK_SIZE) - 1);
331 resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
333 atapi_setup_cmd_resp(ide, channel, sizeof(struct atapi_rd_capacity_resp));
338 static int atapi_get_config(struct ide_internal * ide, struct ide_channel * channel) {
339 struct ide_drive * drive = get_selected_drive(channel);
340 struct atapi_config_cmd * cmd = (struct atapi_config_cmd *)(drive->data_buf);
341 uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
342 struct atapi_config_resp * resp = (struct atapi_config_resp *)(drive->data_buf);
345 memset(resp, 0, sizeof(struct atapi_config_resp));
347 resp->data_len = le_to_be_32(xfer_len - 4);
349 if (alloc_len < xfer_len) {
350 xfer_len = alloc_len;
353 V3_Print(VM_NONE, VCORE_NONE, "ATAPI Get config: xfer_len=%d\b", xfer_len);
355 atapi_setup_cmd_resp(ide, channel, xfer_len);
361 static int atapi_read_toc(struct ide_internal * ide, struct ide_channel * channel) {
362 struct ide_drive * drive = get_selected_drive(channel);
363 struct atapi_rd_toc_cmd * cmd = (struct atapi_rd_toc_cmd *)(drive->data_buf);
364 uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
365 struct atapi_rd_toc_resp * resp = (struct atapi_rd_toc_resp *)(drive->data_buf);
369 memset(resp, 0, sizeof(struct atapi_rd_toc_resp));
371 resp->data_len = le_to_be_16(10);
372 resp->first_track_num = 1;
373 resp->last_track_num = 1;
375 // we don't handle multi session
376 // we'll just treat it the same as single session
377 if ((cmd->format == 0) || (cmd->format == 1)) {
378 memset(&(resp->track_descs[0]), 0, 8);
380 if (alloc_len < xfer_len) {
381 xfer_len = alloc_len;
384 atapi_setup_cmd_resp(ide, channel, xfer_len);
386 PrintError(VM_NONE, VCORE_NONE, "Unhandled Format (%d)\n", cmd->format);
394 static int atapi_mode_sense_cur_values(struct ide_internal * ide, struct ide_channel * channel,
395 struct atapi_mode_sense_cmd * sense_cmd) {
396 struct ide_drive * drive = get_selected_drive(channel);
397 struct atapi_mode_sense_hdr * hdr = (struct atapi_mode_sense_hdr *)(drive->data_buf);
398 uint_t resp_len = sizeof(struct atapi_mode_sense_hdr);
399 uint16_t alloc_len = be_to_le_16(sense_cmd->alloc_len);
400 PrintDebug(VM_NONE, VCORE_NONE,"Page Code: %x\n", sense_cmd->page_code);
401 PrintDebug(VM_NONE, VCORE_NONE,"Alloc len: %d\n", alloc_len);
403 switch (sense_cmd->page_code) {
405 case 0x01: { // error recovery
406 struct atapi_error_recovery * err = NULL;
407 err = (struct atapi_error_recovery *)(drive->data_buf +
408 sizeof(struct atapi_mode_sense_hdr));
411 memcpy(err, &(drive->cd_state.err_recovery), sizeof(struct atapi_error_recovery));
413 resp_len += sizeof(struct atapi_error_recovery);
415 PrintError(VM_NONE, VCORE_NONE,"mode sense (error recovery) resp_len=%d\n", resp_len);
418 hdr->mode_data_len = le_to_be_16(resp_len - 2);
422 case 0x2a: { // CDROM caps and mech. status
424 uint8_t * buf = drive->data_buf;
428 PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
430 *((uint16_t *)buf) = le_to_be_16(28 + 6);
443 /* Claim PLAY_AUDIO capability (0x01) since some Linux
444 code checks for this to automount media. */
447 buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
451 *((uint16_t *)&(buf[16])) = le_to_be_16(706);
454 *((uint16_t *)&(buf[20])) = le_to_be_16(512);
455 *((uint16_t *)&(buf[22])) = le_to_be_16(706);
464 struct atapi_cdrom_caps * caps = NULL;
465 caps = (struct atapi_cdrom_caps *)(drive->data_buf + sizeof(struct atapi_mode_sense_hdr));
470 memset(caps, 0, sizeof(struct atapi_cdrom_caps));
472 resp_len += sizeof(struct atapi_cdrom_caps);
474 hdr->mode_data_len = le_to_be_16(resp_len - 2);
477 PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
479 caps->page_code = 0x2a;
480 caps->page_len = 0x12;
481 caps->mode2_form1 = 1;
482 caps->mode2_form2 = 1;
483 caps->multisession = 1;
487 /* JRL TODO: These are dynamic caps */
489 caps->lock_state = 0;
493 caps->obsolete1 = le_to_be_16(0x2c2);
494 caps->num_vols_supp = le_to_be_16(2);
496 caps->lun_buf_size = le_to_be_16(512);
497 caps->obsolete2 = le_to_be_16(0x2c2);
507 PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense Page Code not supported (%x)\n", sense_cmd->page_code);
508 atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
509 ide_raise_irq(ide, channel);
514 // We do this after error checking, because its only valid if everything worked
515 // memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
516 // hdr->media_type_code = 0x70;
518 PrintDebug(VM_NONE, VCORE_NONE, "resp_len=%d\n", resp_len);
520 drive->transfer_length = (resp_len > alloc_len) ? alloc_len : resp_len;
521 drive->transfer_index = 0;
522 atapi_update_req_len(ide, channel, drive->transfer_length);
524 ide_raise_irq(ide, channel);
530 static int atapi_mode_sense(struct ide_internal * ide, struct ide_channel * channel) {
531 struct ide_drive * drive = get_selected_drive(channel);
532 struct atapi_mode_sense_cmd * sense_cmd = (struct atapi_mode_sense_cmd *)(drive->data_buf);
534 switch (sense_cmd->page_ctrl) {
535 case 0x00: // Current values
536 return atapi_mode_sense_cur_values(ide, channel, sense_cmd);
537 case 0x01: // Changeable values
538 case 0x02: // default values
539 case 0x03: // saved values
541 PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense mode not supported (%x)\n", sense_cmd->page_ctrl);
549 static int atapi_inquiry(struct ide_internal * ide, struct ide_channel * channel) {
550 struct ide_drive * drive = get_selected_drive(channel);
551 struct atapi_inquiry_cmd * inquiry_cmd = (struct atapi_inquiry_cmd *)(drive->data_buf);
552 uint16_t alloc_len = be_to_le_16(inquiry_cmd->alloc_len);
553 struct atapi_inquiry_resp * resp = (struct atapi_inquiry_resp *)(drive->data_buf);
554 int xfer_len = sizeof(struct atapi_inquiry_resp);
555 const char * vendor_id = "VTAB ";
556 const char * product_id = "Turbo CD-ROM ";
557 const char * product_rev = "1.0 ";
559 memset(resp, 0, sizeof(struct atapi_inquiry_resp));
561 resp->dev_type = DEV_TYPE_CDROM;
562 resp->removable_media = 1;
563 resp->resp_data_fmt = 0x1;
564 resp->atapi_trans_ver = 0x2;
565 resp->additional_len = 31;
567 memcpy(resp->t10_vendor_id, vendor_id, strlen(vendor_id));
568 memcpy(resp->product_id, product_id, strlen(product_id));
569 memcpy(resp->product_rev, product_rev, strlen(product_rev));
571 if (alloc_len < xfer_len) {
572 xfer_len = alloc_len;
575 atapi_setup_cmd_resp(ide, channel, xfer_len);
581 static int atapi_mech_status(struct ide_internal * ide, struct ide_channel * channel) {
582 struct ide_drive * drive = get_selected_drive(channel);
583 struct atapi_mech_status_cmd * status_cmd = (struct atapi_mech_status_cmd *)(drive->data_buf);
584 uint16_t alloc_len = be_to_le_16(status_cmd->alloc_len);
585 struct atapi_mech_status_resp * resp = (struct atapi_mech_status_resp *)(drive->data_buf);
586 int xfer_len = sizeof(struct atapi_mech_status_resp);
588 memset(resp, 0, sizeof(struct atapi_mech_status_resp));
590 resp->lba = le_to_be_32(1);
591 resp->slot_table_len = le_to_be_16(0);
593 if (alloc_len < xfer_len) {
594 xfer_len = alloc_len;
597 atapi_setup_cmd_resp(ide, channel, xfer_len);
603 static int atapi_cmd_is_data_op(uint8_t cmd) {
605 case 0x28: // read (10)
606 case 0xa8: // read (12)
607 case 0x2a: // write (10)
608 case 0xaa: // write (12)
616 static int atapi_handle_packet(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
617 struct ide_drive * drive = get_selected_drive(channel);
618 uint8_t cmd = drive->data_buf[0];
620 PrintDebug(core->vm_info, core, "IDE: ATAPI Command %x\n", cmd);
622 drive->cd_state.atapi_cmd = cmd;
625 case 0x00: // test unit ready
626 atapi_cmd_nop(ide, channel);
628 /* if drive not ready:
629 atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
632 case 0x03: // request sense
633 PrintError(core->vm_info, core, "IDE: Requesting Sense (0x3)\n");
634 atapi_req_sense(ide, channel);
637 case 0x1e: // lock door
638 atapi_cmd_nop(ide, channel);
641 case 0x28: // read(10)
642 if (atapi_read10(core, ide, channel) == -1) {
643 PrintError(core->vm_info, core, "IDE: Error in ATAPI read (%x)\n", cmd);
648 case 0x5a: // mode sense
649 if (atapi_mode_sense(ide, channel) == -1) {
650 PrintError(core->vm_info, core, "IDE: Error in ATAPI mode sense (%x)\n", cmd);
656 case 0x25: // read cdrom capacity
657 if (atapi_get_capacity(ide, channel) == -1) {
658 PrintError(core->vm_info, core, "IDE: Error getting CDROM capacity (%x)\n", cmd);
664 case 0x43: // read TOC
665 if (atapi_read_toc(ide, channel) == -1) {
666 PrintError(core->vm_info, core, "IDE: Error getting CDROM TOC (%x)\n", cmd);
671 case 0x46: // get configuration
672 if (atapi_get_config(ide, channel) == -1) {
673 PrintError(core->vm_info, core, "IDE: Error getting CDROM Configuration (%x)\n", cmd);
679 case 0x4a: // Get Status/event
680 case 0x51: // read disk info
681 // no-op to keep the Linux CD-ROM driver happy
682 PrintDebug(core->vm_info, core, "Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
683 atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
684 ide_raise_irq(ide, channel);
687 case 0x12: // inquiry
688 if (atapi_inquiry(ide, channel) == -1) {
689 PrintError(core->vm_info, core, "IDE: Error in ATAPI inquiry (%x)\n", cmd);
694 case 0xbd: // mechanism status
695 if (atapi_mech_status(ide, channel) == -1) {
696 PrintError(core->vm_info, core, "IDE: error in ATAPI Mechanism status query (%x)\n", cmd);
702 case 0xa8: // read(12)
705 case 0x1b: // start/stop drive
706 atapi_cmd_nop(ide,channel);
709 case 0xbe: // read cd
715 case 0x42: // read sub-channel
719 case 0x55: // mode select
720 case 0xa6: // load/unload cd
721 case 0x4b: // pause/resume
722 case 0x45: // play audio
723 case 0x47: // play audio msf
724 case 0xbc: // play cd
725 case 0xb9: // read cd msf
726 case 0x44: // read header
728 case 0xbb: // set cd speed
729 case 0x4e: // stop play/scan
732 PrintError(core->vm_info, core, "Unhandled ATAPI command %x\n", cmd);
733 atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
734 ide_raise_irq(ide, channel);
742 static void atapi_identify_device(struct ide_drive * drive) {
743 struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
744 const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
745 const char* firmware = "ALPHA1 ";
747 drive->transfer_length = 512;
748 drive->transfer_index = 0;
751 memset(drive_id->buf, 0, sizeof(drive_id->buf));
753 drive_id->fixed_drive = 1;
754 drive_id->removable_media = 1;
757 drive_id->disk_speed1 = 1;
758 drive_id->disk_speed3 = 1;
760 drive_id->cdrom_flag = 1;
762 // These buffers do not contain a terminating "\0"
763 memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
764 memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
765 memcpy(drive_id->model_num, drive->model, 40);
768 drive_id->dword_io = 1;
771 /* Disabled until command packet DMA is fixed */
772 drive_id->dma_enable = 1;
775 drive_id->lba_enable = 1;
777 drive_id->rw_multiples = 0x80ff;
779 // words 64-70, 54-58 valid
780 /* Disabled until command packet DMA is fixed */
781 drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
783 // copied from CFA540A
784 /* Disabled until command packet DMA is fixed */
785 drive_id->buf[63] = 0x0103; // variable (DMA stuff)
788 /* uncommented to disable dma(?) */
789 // drive_id->buf[64] = 0x0001; // PIO
792 drive_id->buf[65] = 0x00b4;
793 drive_id->buf[66] = 0x00b4;
794 drive_id->buf[67] = 0x012c;
795 drive_id->buf[68] = 0x00b4;
797 drive_id->buf[71] = 30; // faked
798 drive_id->buf[72] = 30; // faked
800 // drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
801 drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
803 /* Disabled until command packet DMA is fixed */
804 drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;