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.


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