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.


IDE/ATAPI bug fix - allow sense and other requests to read past
[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     drive->cd_state.sense.read_len=0xa;
243
244     memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
245    
246     atapi_setup_cmd_resp(ide, channel, sizeof(drive->cd_state.sense.buf));
247 }
248
249
250
251 static int atapi_get_capacity(struct ide_internal * ide, struct ide_channel * channel) {
252     struct ide_drive * drive = get_selected_drive(channel);
253     struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
254     uint32_t capacity = drive->ops->get_capacity(drive->private_data);
255
256     resp->lba = le_to_be_32((capacity / ATAPI_BLOCK_SIZE) - 1);
257     resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
258
259     atapi_setup_cmd_resp(ide, channel, sizeof(struct atapi_rd_capacity_resp));
260
261     return 0;
262 }
263
264 static int atapi_get_config(struct ide_internal * ide, struct ide_channel * channel) {
265     struct ide_drive * drive = get_selected_drive(channel);
266     struct atapi_config_cmd * cmd = (struct atapi_config_cmd *)(drive->data_buf);
267     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
268     struct atapi_config_resp * resp = (struct atapi_config_resp *)(drive->data_buf);
269     int xfer_len = 8;
270
271     memset(resp, 0, sizeof(struct atapi_config_resp));
272
273     resp->data_len = le_to_be_32(xfer_len - 4);
274
275     if (alloc_len < xfer_len) {
276         xfer_len = alloc_len;
277     }
278     
279     V3_Print(VM_NONE, VCORE_NONE, "ATAPI Get config: xfer_len=%d\b", xfer_len);
280
281     atapi_setup_cmd_resp(ide, channel, xfer_len);
282     
283     return 0;
284 }
285
286
287 static int atapi_read_toc(struct ide_internal * ide, struct ide_channel * channel) {
288     struct ide_drive * drive = get_selected_drive(channel);
289     struct atapi_rd_toc_cmd * cmd = (struct atapi_rd_toc_cmd *)(drive->data_buf);
290     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
291     struct atapi_rd_toc_resp * resp = (struct atapi_rd_toc_resp *)(drive->data_buf);
292
293     int xfer_len = 12;
294
295     memset(resp, 0, sizeof(struct atapi_rd_toc_resp));
296     
297     resp->data_len = le_to_be_16(10);
298     resp->first_track_num = 1;
299     resp->last_track_num = 1;
300
301     // we don't handle multi session
302     // we'll just treat it the same as single session
303     if ((cmd->format == 0) || (cmd->format == 1)) {
304         memset(&(resp->track_descs[0]), 0, 8);
305         
306         if (alloc_len < xfer_len) {
307             xfer_len = alloc_len;
308         }
309
310         atapi_setup_cmd_resp(ide, channel, xfer_len);
311     } else {
312         PrintError(VM_NONE, VCORE_NONE, "Unhandled Format (%d)\n", cmd->format);
313         return -1;
314     }
315
316     return 0;
317 }
318
319
320 static int atapi_mode_sense_cur_values(struct ide_internal * ide, struct ide_channel * channel, 
321                                        struct atapi_mode_sense_cmd * sense_cmd) {
322     struct ide_drive * drive = get_selected_drive(channel);
323     struct atapi_mode_sense_hdr * hdr = (struct atapi_mode_sense_hdr *)(drive->data_buf);
324     uint_t resp_len = sizeof(struct atapi_mode_sense_hdr);
325     uint16_t alloc_len = be_to_le_16(sense_cmd->alloc_len);
326     PrintDebug(VM_NONE, VCORE_NONE,"Page Code: %x\n", sense_cmd->page_code);
327     PrintDebug(VM_NONE, VCORE_NONE,"Alloc len: %d\n", alloc_len);
328
329     switch (sense_cmd->page_code) {
330
331         case 0x01: {    // error recovery
332             struct atapi_error_recovery * err = NULL;
333             err = (struct atapi_error_recovery *)(drive->data_buf + 
334                                                   sizeof(struct atapi_mode_sense_hdr));
335
336
337             memcpy(err, &(drive->cd_state.err_recovery), sizeof(struct atapi_error_recovery));
338
339             resp_len += sizeof(struct atapi_error_recovery);
340
341             PrintError(VM_NONE, VCORE_NONE,"mode sense (error recovery) resp_len=%d\n", resp_len);
342
343
344             hdr->mode_data_len = le_to_be_16(resp_len - 2);
345             
346             break;
347         }
348         case 0x2a: { // CDROM caps and mech. status
349
350             uint8_t * buf = drive->data_buf;
351
352
353
354             PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
355
356             *((uint16_t *)buf) = le_to_be_16(28 + 6);
357             buf[2] = 0x70;
358             buf[3] = 0;
359             buf[4] = 0;
360             buf[5] = 0;
361             buf[6] = 0;
362             buf[7] = 0;
363
364             buf[8] = 0x2a;
365             buf[9] = 0x12;
366             buf[10] = 0x00;
367             buf[11] = 0x00;
368
369             /* Claim PLAY_AUDIO capability (0x01) since some Linux
370                code checks for this to automount media. */
371             buf[12] = 0x71;
372             buf[13] = 3 << 5;
373             buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
374
375             buf[6] |= 1 << 1;
376             buf[15] = 0x00;
377             *((uint16_t *)&(buf[16])) = le_to_be_16(706);
378             buf[18] = 0;
379             buf[19] = 2;
380             *((uint16_t *)&(buf[20])) = le_to_be_16(512);
381             *((uint16_t *)&(buf[22])) = le_to_be_16(706);
382             buf[24] = 0;
383             buf[25] = 0;
384             buf[26] = 0;
385             buf[27] = 0;
386
387             resp_len = 28;
388
389 #if 0
390             struct atapi_cdrom_caps * caps = NULL;
391             caps = (struct atapi_cdrom_caps *)(drive->data_buf + sizeof(struct atapi_mode_sense_hdr));
392             
393
394
395
396             memset(caps, 0, sizeof(struct atapi_cdrom_caps));
397
398             resp_len += sizeof(struct atapi_cdrom_caps);
399
400             hdr->mode_data_len = le_to_be_16(resp_len - 2);
401
402
403             PrintError(VM_NONE, VCORE_NONE, "mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
404
405             caps->page_code = 0x2a;
406             caps->page_len = 0x12;
407             caps->mode2_form1 = 1;
408             caps->mode2_form2 = 1;
409             caps->multisession = 1;
410             caps->isrc = 1;
411             caps->upc = 1;
412
413             /* JRL TODO: These are dynamic caps */
414             caps->lock = 1;
415             caps->lock_state = 0;
416             caps->eject = 1;
417
418             caps->lmt = 1;
419             caps->obsolete1 = le_to_be_16(0x2c2);
420             caps->num_vols_supp = le_to_be_16(2);
421
422             caps->lun_buf_size = le_to_be_16(512);
423             caps->obsolete2 = le_to_be_16(0x2c2);
424
425 #endif
426
427             break;
428         }
429         case 0x0d:
430         case 0x0e:
431         case 0x3f:
432         default:
433             PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense Page Code not supported (%x)\n", sense_cmd->page_code);
434             atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
435             ide_raise_irq(ide, channel);
436             return 0;
437     }
438
439
440     // We do this after error checking, because its only valid if everything worked
441     //    memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
442     // hdr->media_type_code = 0x70;
443
444     PrintDebug(VM_NONE, VCORE_NONE, "resp_len=%d\n", resp_len);
445
446     drive->transfer_length = (resp_len > alloc_len) ? alloc_len : resp_len;
447     drive->transfer_index = 0;
448     atapi_update_req_len(ide, channel, drive->transfer_length);
449
450     ide_raise_irq(ide, channel);
451
452     return 0;
453 }
454
455
456 static int atapi_mode_sense(struct ide_internal * ide, struct ide_channel * channel) {
457     struct ide_drive * drive = get_selected_drive(channel);
458     struct atapi_mode_sense_cmd * sense_cmd = (struct atapi_mode_sense_cmd *)(drive->data_buf);
459
460     switch (sense_cmd->page_ctrl) {
461         case 0x00: // Current values
462             return atapi_mode_sense_cur_values(ide, channel, sense_cmd);
463         case 0x01: // Changeable values
464         case 0x02: // default values
465         case 0x03: // saved values
466         default:
467             PrintError(VM_NONE, VCORE_NONE, "ATAPI: Mode sense mode not supported (%x)\n", sense_cmd->page_ctrl);
468             return -1;
469     }
470     return 0;
471 }
472
473
474
475 static int atapi_inquiry(struct ide_internal * ide, struct ide_channel * channel) {
476     struct ide_drive * drive = get_selected_drive(channel);
477     struct atapi_inquiry_cmd * inquiry_cmd = (struct atapi_inquiry_cmd *)(drive->data_buf);
478     uint16_t alloc_len = be_to_le_16(inquiry_cmd->alloc_len);
479     struct atapi_inquiry_resp * resp = (struct atapi_inquiry_resp *)(drive->data_buf);
480     int xfer_len = sizeof(struct atapi_inquiry_resp);
481     const char * vendor_id = "VTAB    ";
482     const char * product_id = "Turbo CD-ROM    ";
483     const char * product_rev = "1.0 ";
484
485     memset(resp, 0, sizeof(struct atapi_inquiry_resp));
486     
487     resp->dev_type = DEV_TYPE_CDROM;
488     resp->removable_media = 1;
489     resp->resp_data_fmt = 0x1;
490     resp->atapi_trans_ver = 0x2;
491     resp->additional_len = 31;
492
493     memcpy(resp->t10_vendor_id, vendor_id, strlen(vendor_id));
494     memcpy(resp->product_id, product_id, strlen(product_id));
495     memcpy(resp->product_rev, product_rev, strlen(product_rev));
496     
497     if (alloc_len < xfer_len) {
498         xfer_len = alloc_len;
499     }
500
501     atapi_setup_cmd_resp(ide, channel, xfer_len);
502
503     return 0;
504 }
505
506
507 static int atapi_mech_status(struct ide_internal * ide, struct ide_channel * channel) {
508     struct ide_drive * drive = get_selected_drive(channel);
509     struct atapi_mech_status_cmd * status_cmd = (struct atapi_mech_status_cmd *)(drive->data_buf);
510     uint16_t alloc_len = be_to_le_16(status_cmd->alloc_len);
511     struct atapi_mech_status_resp * resp = (struct atapi_mech_status_resp *)(drive->data_buf);
512     int xfer_len = sizeof(struct atapi_mech_status_resp);
513
514     memset(resp, 0, sizeof(struct atapi_mech_status_resp));
515
516     resp->lba = le_to_be_32(1);
517     resp->slot_table_len = le_to_be_16(0);
518     
519     if (alloc_len < xfer_len) {
520         xfer_len = alloc_len;
521     }
522
523     atapi_setup_cmd_resp(ide, channel, xfer_len);
524
525     return 0;
526 }
527
528
529 static int atapi_cmd_is_data_op(uint8_t cmd) {
530     switch (cmd) {
531         case 0x28: // read (10)
532         case 0xa8: // read (12)
533         case 0x2a: // write (10)
534         case 0xaa: // write (12)
535             return 1;
536         default:
537             return 0;
538     } 
539 }
540
541
542 static int atapi_handle_packet(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
543    struct ide_drive * drive = get_selected_drive(channel);
544    uint8_t cmd = drive->data_buf[0];
545
546    PrintDebug(core->vm_info, core, "IDE: ATAPI Command %x\n", cmd);
547
548    drive->cd_state.atapi_cmd = cmd;
549
550    switch (cmd) {
551        case 0x00: // test unit ready
552            atapi_cmd_nop(ide, channel);
553
554            /* if drive not ready: 
555               atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
556            */
557            break;
558        case 0x03: // request sense
559            PrintError(core->vm_info, core, "IDE: Requesting Sense (0x3)\n");
560            atapi_req_sense(ide, channel);
561            break;
562
563        case 0x1e: // lock door
564            atapi_cmd_nop(ide, channel);
565            break;
566
567        case 0x28: // read(10)
568            if (atapi_read10(core, ide, channel) == -1) {
569                PrintError(core->vm_info, core, "IDE: Error in ATAPI read (%x)\n", cmd);
570                return -1;
571            }
572            break;
573
574        case 0x5a: // mode sense
575            if (atapi_mode_sense(ide, channel) == -1) {
576                PrintError(core->vm_info, core, "IDE: Error in ATAPI mode sense (%x)\n", cmd);
577                return -1;
578            }
579            break;
580
581
582        case 0x25: // read cdrom capacity
583            if (atapi_get_capacity(ide, channel) == -1) {
584                PrintError(core->vm_info, core, "IDE: Error getting CDROM capacity (%x)\n", cmd);
585                return -1;
586            }
587            break;
588
589
590        case 0x43: // read TOC
591            if (atapi_read_toc(ide, channel) == -1) {
592                PrintError(core->vm_info, core, "IDE: Error getting CDROM TOC (%x)\n", cmd);
593                return -1;
594            }
595            break;
596
597        case 0x46: // get configuration
598            if (atapi_get_config(ide, channel) == -1) {
599                PrintError(core->vm_info, core, "IDE: Error getting CDROM Configuration (%x)\n", cmd);
600                return -1;
601            }
602            break;
603
604
605        case 0x4a: // Get Status/event
606        case 0x51: // read disk info
607            // no-op to keep the Linux CD-ROM driver happy
608            PrintDebug(core->vm_info, core, "Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
609            atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
610            ide_raise_irq(ide, channel);
611            break;
612
613        case 0x12: // inquiry
614            if (atapi_inquiry(ide, channel) == -1) {
615                PrintError(core->vm_info, core, "IDE: Error in ATAPI inquiry (%x)\n", cmd);
616                return -1;
617            }
618            break;
619
620        case 0xbd: // mechanism status 
621            if (atapi_mech_status(ide, channel) == -1) {
622                PrintError(core->vm_info, core, "IDE: error in ATAPI Mechanism status query (%x)\n", cmd);
623                return -1;
624            }
625            break;
626
627
628        case 0xa8: // read(12)
629
630
631        case 0x1b: // start/stop drive
632          atapi_cmd_nop(ide,channel);
633          break;
634
635        case 0xbe: // read cd
636
637
638
639        case 0x2b: // seek
640
641        case 0x42: // read sub-channel
642
643
644            
645        case 0x55: // mode select
646        case 0xa6: // load/unload cd
647        case 0x4b: // pause/resume
648        case 0x45: // play audio
649        case 0x47: // play audio msf
650        case 0xbc: // play cd
651        case 0xb9: // read cd msf
652        case 0x44: // read header
653        case 0xba: // scan
654        case 0xbb: // set cd speed
655        case 0x4e: // stop play/scan
656
657        default:
658            PrintError(core->vm_info, core, "Unhandled ATAPI command %x\n", cmd);
659            atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
660            ide_raise_irq(ide, channel);
661            return -1;
662    }
663    
664    return 0;
665 }
666
667
668 static void atapi_identify_device(struct ide_drive * drive) {
669     struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
670     const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
671     const char* firmware = "ALPHA1  ";
672
673     drive->transfer_length = 512;
674     drive->transfer_index = 0;
675
676
677     memset(drive_id->buf, 0, sizeof(drive_id->buf));
678
679     drive_id->fixed_drive = 1;
680     drive_id->removable_media = 1;
681
682     // Black magic...
683     drive_id->disk_speed1 = 1;
684     drive_id->disk_speed3 = 1;
685
686     drive_id->cdrom_flag = 1;
687
688     // These buffers do not contain a terminating "\0"
689     memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
690     memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
691     memcpy(drive_id->model_num, drive->model, 40);
692
693     // 32 bits access
694     drive_id->dword_io = 1;
695
696     // enable DMA access
697     /* Disabled until command packet DMA is fixed */
698     drive_id->dma_enable = 1;
699
700     // enable LBA access
701     drive_id->lba_enable = 1;
702     
703     drive_id->rw_multiples = 0x80ff;
704
705     // words 64-70, 54-58 valid
706     /* Disabled until command packet DMA is fixed */
707         drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
708
709     // copied from CFA540A
710     /* Disabled until command packet DMA is fixed */
711      drive_id->buf[63] = 0x0103; // variable (DMA stuff)
712        
713
714     /* uncommented to disable dma(?) */
715      // drive_id->buf[64] = 0x0001; // PIO
716
717
718     drive_id->buf[65] = 0x00b4;
719     drive_id->buf[66] = 0x00b4;
720     drive_id->buf[67] = 0x012c;
721     drive_id->buf[68] = 0x00b4;
722
723     drive_id->buf[71] = 30; // faked
724     drive_id->buf[72] = 30; // faked
725
726     //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
727     drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
728
729     /* Disabled until command packet DMA is fixed */
730     drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
731 }
732
733 #endif