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.


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