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.


0cc9f269bc78fb93f39d6c55e0b9b9fdbf32791c
[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 #ifndef __DEVICES_ATAPI_H__
21 #define __DEVICES_ATAPI_H__
22
23 #define ATAPI_PACKET_SIZE 12
24
25 #include "atapi-types.h"
26
27
28
29 /* ATAPI sucks...
30  * The OS will write to the cylinder register the number of bytes it wants to read 
31  * however the device can change that value 
32  * 
33  */
34 static int atapi_update_req_len(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
35     struct ide_drive * drive = get_selected_drive(channel);
36
37     //PrintDebug("\tUpdating request length (pre=%d)\n", drive->req_len);
38
39     if (drive->req_len == 0) {
40         PrintError(VM_NONE,VCORE_NONE, "ATAPI Error: request of length 0\n");
41         return -1;
42     }
43
44
45     channel->status.busy = 0;
46     channel->status.data_req = 1;
47     channel->status.error = 0;
48
49     drive->irq_flags.io_dir = 1;
50     drive->irq_flags.c_d = 0;
51
52     // make count even
53     if (drive->req_len % 2) {
54         drive->req_len -= 1;
55     }
56
57     // if the device can't return as much as the OS requested
58     // this is actually a decrement of the req_len by the amount requested by the OS
59     if (drive->req_len > xfer_len) {
60         drive->req_len = xfer_len;
61     }
62
63     //    PrintDebug("\tUpdating request length (post=%d)\n", drive->req_len);
64
65     return 0;
66 }
67
68
69
70 // This is for simple commands that don't need to sanity check the req_len
71 static void atapi_setup_cmd_resp(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
72     struct ide_drive * drive = get_selected_drive(channel);
73
74     drive->transfer_length = xfer_len;
75     drive->transfer_index = 0;
76     drive->req_len = drive->transfer_length;
77
78     drive->irq_flags.io_dir = 1;
79     drive->irq_flags.c_d = 0;
80
81     channel->status.busy = 0;
82     channel->status.error = 0;
83
84     if (drive->transfer_length > 0) {
85         channel->status.data_req = 1;
86     }
87
88     ide_raise_irq(ide, channel);
89 }
90
91 static void atapi_cmd_error(struct ide_internal * ide, struct ide_channel * channel, 
92                      atapi_sense_key_t  sense_key, atapi_add_sense_code_t asc) {
93     struct ide_drive * drive = get_selected_drive(channel);
94
95     // overload error register with ATAPI value
96     channel->error_reg.val = sense_key << 4;
97     
98     channel->status.busy = 0;
99     channel->status.ready = 1;
100     channel->status.write_fault = 0;
101     channel->status.data_req = 0;
102     channel->status.error = 1;
103   
104     drive->cd_state.sense.header = 0xf0;
105     drive->cd_state.sense.rsvd1 = 0x00;
106     drive->cd_state.sense.read_len = 0x0a;
107     drive->cd_state.sense.sense_key = sense_key;
108     drive->cd_state.sense.asc = asc;
109
110
111     drive->irq_flags.io_dir = 1;
112     drive->irq_flags.c_d = 1;
113     drive->irq_flags.rel = 0;
114
115     ide_raise_irq(ide, channel);
116 }
117
118
119 static void atapi_cmd_nop(struct ide_internal * ide, struct ide_channel * channel) {
120     struct ide_drive * drive = get_selected_drive(channel);
121
122     channel->status.busy = 0;
123     channel->status.ready = 1;
124     channel->status.data_req = 0;
125     channel->status.error = 0;
126
127     drive->irq_flags.io_dir = 1;
128     drive->irq_flags.c_d = 1;
129     drive->irq_flags.rel = 0;
130
131     ide_raise_irq(ide, channel);
132 }
133
134
135
136 static int atapi_read_chunk(struct ide_internal * ide, struct ide_channel * channel) {
137     struct ide_drive * drive = get_selected_drive(channel);
138
139     int ret = drive->ops->read(drive->data_buf, 
140                                drive->current_lba * ATAPI_BLOCK_SIZE, 
141                                ATAPI_BLOCK_SIZE, drive->private_data);
142     
143     if (ret == -1) {
144         PrintError(VM_NONE,VCORE_NONE, "IDE: Error reading CD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
145         return -1;
146     }
147
148     return 0;
149 }
150
151
152 static int atapi_update_data_buf(struct ide_internal * ide, struct ide_channel * channel) {
153     struct ide_drive * drive = get_selected_drive(channel);    
154     
155     switch (drive->cd_state.atapi_cmd) {
156         case 0x28: // read(10)
157         case 0xa8: // read(12)
158
159             // Update lba address to point to next block  
160             drive->current_lba++;
161
162             // read the next block
163             return atapi_read_chunk(ide, channel);
164
165         default:
166             PrintError(VM_NONE,VCORE_NONE, "Unhandled ATAPI command in update buffer %x\n", drive->cd_state.atapi_cmd);
167             return -1;
168     }
169
170     return 0;
171 }
172
173 static int atapi_read10(struct guest_info * core, 
174                         struct ide_internal * ide,
175                         struct ide_channel * channel) {
176     struct ide_drive * drive = get_selected_drive(channel);
177     struct atapi_read10_cmd * cmd = (struct atapi_read10_cmd *)(drive->data_buf);
178     uint32_t lba =  be_to_le_32(cmd->lba);
179     uint16_t xfer_len = be_to_le_16(cmd->xfer_len);
180
181     PrintDebug(core->vm_info, core, "READ10: XferLen=%d ; LBA=%x \n", xfer_len, lba );
182
183     /* Check if cd is ready
184      * if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
185      */
186     
187     if (xfer_len == 0) {
188         atapi_cmd_nop(ide, channel);
189         return 0;
190     }
191     
192     if ((lba + xfer_len) > (drive->ops->get_capacity(drive->private_data) / ATAPI_BLOCK_SIZE)) {
193         PrintError(core->vm_info, core, "IDE: xfer len exceeded capacity (lba=%d) (xfer_len=%d) (ReadEnd=%d) (capacity=%d)\n", 
194                    lba, xfer_len, lba + xfer_len, 
195                    (uint32_t)drive->ops->get_capacity(drive->private_data));
196         atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
197         ide_raise_irq(ide, channel);
198         return 0;
199     }
200         
201     // PrintDebug(core->vm_info, core, "Reading %d blocks from LBA 0x%x\n", xfer_len, lba);
202     drive->current_lba = lba;
203         
204     // Update the request length value in the cylinder registers
205     drive->transfer_length = xfer_len * ATAPI_BLOCK_SIZE;
206     drive->transfer_index = 0;  
207
208     if (channel->features.dma) {
209
210         if (channel->dma_status.active == 1) {
211             if (dma_read(core, ide, channel) == -1) {
212                 PrintError(core->vm_info, core, "Error in DMA read for CD Read10 command\n");
213                 return -1;
214             }
215         }
216         return 0;
217     }
218
219     if (atapi_read_chunk(ide, channel) == -1) {
220         PrintError(core->vm_info, core, "IDE: Could not read initial chunk from CD\n");
221         return -1;
222     }
223         
224     // Length of ATAPI buffer sits in cylinder registers
225     // This is weird... The host sets this value to say what it would like to transfer, 
226     // if it is larger than the correct size, the device shrinks it to the correct size
227     if (atapi_update_req_len(ide, channel, ATAPI_BLOCK_SIZE) == -1) {
228         PrintError(core->vm_info, core, "Could not update initial request length\n");
229         return -1;
230     }
231     
232     ide_raise_irq(ide, channel);
233
234     return 0;
235 }
236
237
238
239 static void atapi_req_sense(struct ide_internal * ide, struct ide_channel * channel) {
240     struct ide_drive * drive = get_selected_drive(channel);
241
242     memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
243    
244     atapi_setup_cmd_resp(ide, channel, 18);
245 }
246
247
248
249 static int atapi_get_capacity(struct ide_internal * ide, struct ide_channel * channel) {
250     struct ide_drive * drive = get_selected_drive(channel);
251     struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
252     uint32_t capacity = drive->ops->get_capacity(drive->private_data);
253
254     resp->lba = le_to_be_32((capacity / ATAPI_BLOCK_SIZE) - 1);
255     resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
256
257     atapi_setup_cmd_resp(ide, channel, sizeof(struct atapi_rd_capacity_resp));
258
259     return 0;
260 }
261
262 static int atapi_get_config(struct ide_internal * ide, struct ide_channel * channel) {
263     struct ide_drive * drive = get_selected_drive(channel);
264     struct atapi_config_cmd * cmd = (struct atapi_config_cmd *)(drive->data_buf);
265     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
266     struct atapi_config_resp * resp = (struct atapi_config_resp *)(drive->data_buf);
267     int xfer_len = 8;
268
269     memset(resp, 0, sizeof(struct atapi_config_resp));
270
271     resp->data_len = le_to_be_32(xfer_len - 4);
272
273     if (alloc_len < xfer_len) {
274         xfer_len = alloc_len;
275     }
276     
277     V3_Print(VM_NONE, VCORE_NONE, "ATAPI Get config: xfer_len=%d\b", xfer_len);
278
279     atapi_setup_cmd_resp(ide, channel, xfer_len);
280     
281     return 0;
282 }
283
284
285 static int atapi_read_toc(struct ide_internal * ide, struct ide_channel * channel) {
286     struct ide_drive * drive = get_selected_drive(channel);
287     struct atapi_rd_toc_cmd * cmd = (struct atapi_rd_toc_cmd *)(drive->data_buf);
288     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
289     struct atapi_rd_toc_resp * resp = (struct atapi_rd_toc_resp *)(drive->data_buf);
290
291     int xfer_len = 12;
292
293     memset(resp, 0, sizeof(struct atapi_rd_toc_resp));
294     
295     resp->data_len = le_to_be_16(10);
296     resp->first_track_num = 1;
297     resp->last_track_num = 1;
298
299     // we don't handle multi session
300     // we'll just treat it the same as single session
301     if ((cmd->format == 0) || (cmd->format == 1)) {
302         memset(&(resp->track_descs[0]), 0, 8);
303         
304         if (alloc_len < xfer_len) {
305             xfer_len = alloc_len;
306         }
307
308         atapi_setup_cmd_resp(ide, channel, xfer_len);
309     } else {
310         PrintError(VM_NONE, VCORE_NONE, "Unhandled Format (%d)\n", cmd->format);
311         return -1;
312     }
313
314     return 0;
315 }
316
317
318 static int atapi_mode_sense_cur_values(struct ide_internal * ide, struct ide_channel * channel, 
319                                        struct atapi_mode_sense_cmd * sense_cmd) {
320     struct ide_drive * drive = get_selected_drive(channel);
321     struct atapi_mode_sense_hdr * hdr = (struct atapi_mode_sense_hdr *)(drive->data_buf);
322     uint_t resp_len = sizeof(struct atapi_mode_sense_hdr);
323     uint16_t alloc_len = be_to_le_16(sense_cmd->alloc_len);
324     PrintDebug(VM_NONE, VCORE_NONE,"Page Code: %x\n", sense_cmd->page_code);
325     PrintDebug(VM_NONE, VCORE_NONE,"Alloc len: %d\n", alloc_len);
326
327     switch (sense_cmd->page_code) {
328
329         case 0x01: {    // error recovery
330             struct atapi_error_recovery * err = NULL;
331             err = (struct atapi_error_recovery *)(drive->data_buf + 
332                                                   sizeof(struct atapi_mode_sense_hdr));
333
334
335             memcpy(err, &(drive->cd_state.err_recovery), sizeof(struct atapi_error_recovery));
336
337             resp_len += sizeof(struct atapi_error_recovery);
338
339             PrintError(VM_NONE, VCORE_NONE,"mode sense (error recovery) resp_len=%d\n", resp_len);
340
341
342             hdr->mode_data_len = le_to_be_16(resp_len - 2);
343             
344             break;
345         }
346         case 0x2a: { // CDROM caps and mech. status
347
348             uint8_t * buf = drive->data_buf;
349
350
351
352             PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
353
354             *((uint16_t *)buf) = le_to_be_16(28 + 6);
355             buf[2] = 0x70;
356             buf[3] = 0;
357             buf[4] = 0;
358             buf[5] = 0;
359             buf[6] = 0;
360             buf[7] = 0;
361
362             buf[8] = 0x2a;
363             buf[9] = 0x12;
364             buf[10] = 0x00;
365             buf[11] = 0x00;
366
367             /* Claim PLAY_AUDIO capability (0x01) since some Linux
368                code checks for this to automount media. */
369             buf[12] = 0x71;
370             buf[13] = 3 << 5;
371             buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
372
373             buf[6] |= 1 << 1;
374             buf[15] = 0x00;
375             *((uint16_t *)&(buf[16])) = le_to_be_16(706);
376             buf[18] = 0;
377             buf[19] = 2;
378             *((uint16_t *)&(buf[20])) = le_to_be_16(512);
379             *((uint16_t *)&(buf[22])) = le_to_be_16(706);
380             buf[24] = 0;
381             buf[25] = 0;
382             buf[26] = 0;
383             buf[27] = 0;
384
385             resp_len = 28;
386
387 #if 0
388             struct atapi_cdrom_caps * caps = NULL;
389             caps = (struct atapi_cdrom_caps *)(drive->data_buf + sizeof(struct atapi_mode_sense_hdr));
390             
391
392
393
394             memset(caps, 0, sizeof(struct atapi_cdrom_caps));
395
396             resp_len += sizeof(struct atapi_cdrom_caps);
397
398             hdr->mode_data_len = le_to_be_16(resp_len - 2);
399
400
401             PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
402
403             caps->page_code = 0x2a;
404             caps->page_len = 0x12;
405             caps->mode2_form1 = 1;
406             caps->mode2_form2 = 1;
407             caps->multisession = 1;
408             caps->isrc = 1;
409             caps->upc = 1;
410
411             /* JRL TODO: These are dynamic caps */
412             caps->lock = 1;
413             caps->lock_state = 0;
414             caps->eject = 1;
415
416             caps->lmt = 1;
417             caps->obsolete1 = le_to_be_16(0x2c2);
418             caps->num_vols_supp = le_to_be_16(2);
419
420             caps->lun_buf_size = le_to_be_16(512);
421             caps->obsolete2 = le_to_be_16(0x2c2);
422
423 #endif
424
425             break;
426         }
427         case 0x0d:
428         case 0x0e:
429         case 0x3f:
430         default:
431             PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense Page Code not supported (%x)\n", sense_cmd->page_code);
432             atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
433             ide_raise_irq(ide, channel);
434             return 0;
435     }
436
437
438     // We do this after error checking, because its only valid if everything worked
439     //    memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
440     // hdr->media_type_code = 0x70;
441
442     PrintDebug(VM_NONE, VCORE_NONE, "resp_len=%d\n", resp_len);
443
444     drive->transfer_length = (resp_len > alloc_len) ? alloc_len : resp_len;
445     drive->transfer_index = 0;
446     atapi_update_req_len(ide, channel, drive->transfer_length);
447
448     ide_raise_irq(ide, channel);
449
450     return 0;
451 }
452
453
454 static int atapi_mode_sense(struct ide_internal * ide, struct ide_channel * channel) {
455     struct ide_drive * drive = get_selected_drive(channel);
456     struct atapi_mode_sense_cmd * sense_cmd = (struct atapi_mode_sense_cmd *)(drive->data_buf);
457
458     switch (sense_cmd->page_ctrl) {
459         case 0x00: // Current values
460             return atapi_mode_sense_cur_values(ide, channel, sense_cmd);
461         case 0x01: // Changeable values
462         case 0x02: // default values
463         case 0x03: // saved values
464         default:
465             PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense mode not supported (%x)\n", sense_cmd->page_ctrl);
466             return -1;
467     }
468     return 0;
469 }
470
471
472
473 static int atapi_inquiry(struct ide_internal * ide, struct ide_channel * channel) {
474     struct ide_drive * drive = get_selected_drive(channel);
475     struct atapi_inquiry_cmd * inquiry_cmd = (struct atapi_inquiry_cmd *)(drive->data_buf);
476     uint16_t alloc_len = be_to_le_16(inquiry_cmd->alloc_len);
477     struct atapi_inquiry_resp * resp = (struct atapi_inquiry_resp *)(drive->data_buf);
478     int xfer_len = sizeof(struct atapi_inquiry_resp);
479     const char * vendor_id = "VTAB    ";
480     const char * product_id = "Turbo CD-ROM    ";
481     const char * product_rev = "1.0 ";
482
483     memset(resp, 0, sizeof(struct atapi_inquiry_resp));
484     
485     resp->dev_type = DEV_TYPE_CDROM;
486     resp->removable_media = 1;
487     resp->resp_data_fmt = 0x1;
488     resp->atapi_trans_ver = 0x2;
489     resp->additional_len = 31;
490
491     memcpy(resp->t10_vendor_id, vendor_id, strlen(vendor_id));
492     memcpy(resp->product_id, product_id, strlen(product_id));
493     memcpy(resp->product_rev, product_rev, strlen(product_rev));
494     
495     if (alloc_len < xfer_len) {
496         xfer_len = alloc_len;
497     }
498
499     atapi_setup_cmd_resp(ide, channel, xfer_len);
500
501     return 0;
502 }
503
504
505 static int atapi_mech_status(struct ide_internal * ide, struct ide_channel * channel) {
506     struct ide_drive * drive = get_selected_drive(channel);
507     struct atapi_mech_status_cmd * status_cmd = (struct atapi_mech_status_cmd *)(drive->data_buf);
508     uint16_t alloc_len = be_to_le_16(status_cmd->alloc_len);
509     struct atapi_mech_status_resp * resp = (struct atapi_mech_status_resp *)(drive->data_buf);
510     int xfer_len = sizeof(struct atapi_mech_status_resp);
511
512     memset(resp, 0, sizeof(struct atapi_mech_status_resp));
513
514     resp->lba = le_to_be_32(1);
515     resp->slot_table_len = le_to_be_16(0);
516     
517     if (alloc_len < xfer_len) {
518         xfer_len = alloc_len;
519     }
520
521     atapi_setup_cmd_resp(ide, channel, xfer_len);
522
523     return 0;
524 }
525
526
527 static int atapi_cmd_is_data_op(uint8_t cmd) {
528     switch (cmd) {
529         case 0x28: // read (10)
530         case 0xa8: // read (12)
531         case 0x2a: // write (10)
532         case 0xaa: // write (12)
533             return 1;
534         default:
535             return 0;
536     } 
537 }
538
539
540 static int atapi_handle_packet(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
541    struct ide_drive * drive = get_selected_drive(channel);
542    uint8_t cmd = drive->data_buf[0];
543
544    PrintDebug(core->vm_info, core, "IDE: ATAPI Command %x\n", cmd);
545
546    drive->cd_state.atapi_cmd = cmd;
547
548    switch (cmd) {
549        case 0x00: // test unit ready
550            atapi_cmd_nop(ide, channel);
551
552            /* if drive not ready: 
553               atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
554            */
555            break;
556        case 0x03: // request sense
557            PrintError(core->vm_info, core, "IDE: Requesting Sense (0x3)\n");
558            atapi_req_sense(ide, channel);
559            break;
560
561        case 0x1e: // lock door
562            atapi_cmd_nop(ide, channel);
563            break;
564
565        case 0x28: // read(10)
566            if (atapi_read10(core, ide, channel) == -1) {
567                PrintError(core->vm_info, core, "IDE: Error in ATAPI read (%x)\n", cmd);
568                return -1;
569            }
570            break;
571
572        case 0x5a: // mode sense
573            if (atapi_mode_sense(ide, channel) == -1) {
574                PrintError(core->vm_info, core, "IDE: Error in ATAPI mode sense (%x)\n", cmd);
575                return -1;
576            }
577            break;
578
579
580        case 0x25: // read cdrom capacity
581            if (atapi_get_capacity(ide, channel) == -1) {
582                PrintError(core->vm_info, core, "IDE: Error getting CDROM capacity (%x)\n", cmd);
583                return -1;
584            }
585            break;
586
587
588        case 0x43: // read TOC
589            if (atapi_read_toc(ide, channel) == -1) {
590                PrintError(core->vm_info, core, "IDE: Error getting CDROM TOC (%x)\n", cmd);
591                return -1;
592            }
593            break;
594
595        case 0x46: // get configuration
596            if (atapi_get_config(ide, channel) == -1) {
597                PrintError(core->vm_info, core, "IDE: Error getting CDROM Configuration (%x)\n", cmd);
598                return -1;
599            }
600            break;
601
602
603        case 0x4a: // Get Status/event
604        case 0x51: // read disk info
605            // no-op to keep the Linux CD-ROM driver happy
606            PrintDebug(core->vm_info, core, "Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
607            atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
608            ide_raise_irq(ide, channel);
609            break;
610
611        case 0x12: // inquiry
612            if (atapi_inquiry(ide, channel) == -1) {
613                PrintError(core->vm_info, core, "IDE: Error in ATAPI inquiry (%x)\n", cmd);
614                return -1;
615            }
616            break;
617
618        case 0xbd: // mechanism status 
619            if (atapi_mech_status(ide, channel) == -1) {
620                PrintError(core->vm_info, core, "IDE: error in ATAPI Mechanism status query (%x)\n", cmd);
621                return -1;
622            }
623            break;
624
625
626        case 0xa8: // read(12)
627
628
629        case 0x1b: // start/stop drive
630          atapi_cmd_nop(ide,channel);
631          break;
632
633        case 0xbe: // read cd
634
635
636
637        case 0x2b: // seek
638
639        case 0x42: // read sub-channel
640
641
642            
643        case 0x55: // mode select
644        case 0xa6: // load/unload cd
645        case 0x4b: // pause/resume
646        case 0x45: // play audio
647        case 0x47: // play audio msf
648        case 0xbc: // play cd
649        case 0xb9: // read cd msf
650        case 0x44: // read header
651        case 0xba: // scan
652        case 0xbb: // set cd speed
653        case 0x4e: // stop play/scan
654
655        default:
656            PrintError(core->vm_info, core, "Unhandled ATAPI command %x\n", cmd);
657            atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
658            ide_raise_irq(ide, channel);
659            return -1;
660    }
661    
662    return 0;
663 }
664
665
666 static void atapi_identify_device(struct ide_drive * drive) {
667     struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
668     const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
669     const char* firmware = "ALPHA1  ";
670
671     drive->transfer_length = 512;
672     drive->transfer_index = 0;
673
674
675     memset(drive_id->buf, 0, sizeof(drive_id->buf));
676
677     drive_id->fixed_drive = 1;
678     drive_id->removable_media = 1;
679
680     // Black magic...
681     drive_id->disk_speed1 = 1;
682     drive_id->disk_speed3 = 1;
683
684     drive_id->cdrom_flag = 1;
685
686     // These buffers do not contain a terminating "\0"
687     memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
688     memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
689     memcpy(drive_id->model_num, drive->model, 40);
690
691     // 32 bits access
692     drive_id->dword_io = 1;
693
694     // enable DMA access
695     /* Disabled until command packet DMA is fixed */
696     drive_id->dma_enable = 1;
697
698     // enable LBA access
699     drive_id->lba_enable = 1;
700     
701     drive_id->rw_multiples = 0x80ff;
702
703     // words 64-70, 54-58 valid
704     /* Disabled until command packet DMA is fixed */
705         drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
706
707     // copied from CFA540A
708     /* Disabled until command packet DMA is fixed */
709      drive_id->buf[63] = 0x0103; // variable (DMA stuff)
710        
711
712     /* uncommented to disable dma(?) */
713      // drive_id->buf[64] = 0x0001; // PIO
714
715
716     drive_id->buf[65] = 0x00b4;
717     drive_id->buf[66] = 0x00b4;
718     drive_id->buf[67] = 0x012c;
719     drive_id->buf[68] = 0x00b4;
720
721     drive_id->buf[71] = 30; // faked
722     drive_id->buf[72] = 30; // faked
723
724     //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
725     drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
726
727     /* Disabled until command packet DMA is fixed */
728     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
729 }
730
731 #endif