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.


added atapi handlers
[palacios.git] / palacios / src / devices / ide.c
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 #include <palacios/vmm.h>
21 #include <devices/ide.h>
22 #include "ide-types.h"
23 #include "atapi-types.h"
24
25 #define PRI_DEFAULT_IRQ 14
26 #define SEC_DEFAULT_IRQ 15
27
28
29 #define PRI_DATA_PORT         0x1f0
30 #define PRI_FEATURES_PORT     0x1f1
31 #define PRI_SECT_CNT_PORT     0x1f2
32 #define PRI_SECT_NUM_PORT     0x1f3
33 #define PRI_CYL_LOW_PORT      0x1f4
34 #define PRI_CYL_HIGH_PORT     0x1f5
35 #define PRI_DRV_SEL_PORT      0x1f6
36 #define PRI_CMD_PORT          0x1f7
37 #define PRI_CTRL_PORT         0x3f6
38 #define PRI_ADDR_REG_PORT     0x3f7
39
40 #define SEC_DATA_PORT         0x170
41 #define SEC_FEATURES_PORT     0x171
42 #define SEC_SECT_CNT_PORT     0x172
43 #define SEC_SECT_NUM_PORT     0x173
44 #define SEC_CYL_LOW_PORT      0x174
45 #define SEC_CYL_HIGH_PORT     0x175
46 #define SEC_DRV_SEL_PORT      0x176
47 #define SEC_CMD_PORT          0x177
48 #define SEC_CTRL_PORT         0x376
49 #define SEC_ADDR_REG_PORT     0x377
50
51
52 #define DATA_BUFFER_SIZE 2048
53
54 static const char * ide_dev_type_strs[] = {"HARDDISK", "CDROM", "NONE"};
55
56
57 static inline const char * device_type_to_str(v3_ide_dev_type_t type) {
58     if (type > 2) {
59         return NULL;
60     }
61
62     return ide_dev_type_strs[type];
63 }
64
65
66
67 struct ide_cd_state {
68     struct atapi_sense_data sense;
69     uint_t current_lba;
70 };
71
72 struct ide_hd_state {
73
74 };
75
76 struct ide_drive {
77     // Command Registers
78
79     v3_ide_dev_type_t drive_type;
80
81     union {
82         struct v3_ide_cd_ops * cd_ops;
83         struct v3_ide_hd_ops * hd_ops;
84     };
85
86
87     union {
88         struct ide_cd_state cd_state;
89         struct ide_hd_state hd_state;
90     };
91
92     char model[41];
93
94     // Where we are in the data transfer
95     uint_t transfer_index;
96
97     // the length of a transfer
98     // calculated for easy access
99     uint_t transfer_length;
100
101     // We have a local data buffer that we use for IO port accesses
102     uint8_t data_buf[DATA_BUFFER_SIZE];
103
104     void * private_data;
105
106     uint8_t sector_count;             // 0x1f2,0x172
107     uint8_t sector_num;               // 0x1f3,0x173
108     union {
109         uint16_t cylinder;
110         struct {
111             uint8_t cylinder_low;       // 0x1f4,0x174
112             uint8_t cylinder_high;      // 0x1f5,0x175
113         } __attribute__((packed));
114     } __attribute__((packed));
115
116
117 };
118
119
120
121 struct ide_channel {
122     struct ide_drive drives[2];
123
124     // Command Registers
125     struct ide_error_reg error_reg;     // [read] 0x1f1,0x171
126
127     struct ide_features_reg features;
128
129     struct ide_drive_head_reg drive_head; // 0x1f6,0x176
130
131     struct ide_status_reg status;       // [read] 0x1f7,0x177
132     uint8_t cmd_reg;                // [write] 0x1f7,0x177
133
134     int irq; // this is temporary until we add PCI support
135
136     // Control Registers
137     struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
138 };
139
140
141
142 struct ide_internal {
143     struct ide_channel channels[2];
144 };
145
146
147
148 static inline uint32_t be_to_le_16(const uint16_t val) {
149     uint8_t * buf = (uint8_t *)&val;
150     return (buf[0] << 8) | (buf[1]) ;
151 }
152
153
154 static inline uint32_t be_to_le_32(const uint32_t val) {
155     uint8_t * buf = (uint8_t *)&val;
156     return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
157 }
158
159
160 static inline int get_channel_index(ushort_t port) {
161     if (((port & 0xfff8) == 0x1f0) ||
162         ((port & 0xfffe) == 0x3f6)) {
163         return 0;
164     } else if (((port & 0xfff8) == 0x170) ||
165                ((port & 0xfffe) == 0x376)) {
166         return 1;
167     }
168
169     return -1;
170 }
171
172 static inline struct ide_channel * get_selected_channel(struct ide_internal * ide, ushort_t port) {
173     int channel_idx = get_channel_index(port);    
174     return &(ide->channels[channel_idx]);
175 }
176
177 static inline struct ide_drive * get_selected_drive(struct ide_channel * channel) {
178     return &(channel->drives[channel->drive_head.drive_sel]);
179 }
180
181
182 static inline int is_lba_enabled(struct ide_channel * channel) {
183     return channel->drive_head.lba_mode;
184 }
185
186
187 static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
188     if (channel->ctrl_reg.irq_disable == 0) {
189         v3_raise_irq(dev->vm, channel->irq);
190     }
191 }
192
193
194 static void drive_reset(struct ide_drive * drive) {
195     drive->sector_count = 0x01;
196     drive->sector_num = 0x01;
197     
198     if (drive->drive_type == IDE_CDROM) {
199         drive->cylinder = 0xeb14;
200     } else {
201         drive->cylinder = 0x0000;
202     }
203
204
205     memset(drive->data_buf, 0, sizeof(drive->data_buf));
206     drive->transfer_length = 0;
207     drive->transfer_index = 0;
208
209     // Send the reset signal to the connected device callbacks
210     //     channel->drives[0].reset();
211     //    channel->drives[1].reset();
212 }
213
214 static void channel_reset(struct ide_channel * channel) {
215     
216     // set busy and seek complete flags
217     channel->status.val = 0x90;
218
219     // Clear errors
220     channel->error_reg.val = 0x01;
221
222     // clear commands
223     channel->cmd_reg = 0x00;
224
225     channel->ctrl_reg.irq_disable = 0;
226 }
227
228 static void channel_reset_complete(struct ide_channel * channel) {
229     channel->status.busy = 0;
230     channel->status.ready = 1;
231
232     channel->drive_head.head_num = 0;    
233     
234     drive_reset(&(channel->drives[0]));
235     drive_reset(&(channel->drives[1]));
236 }
237
238
239 static void ide_abort_command(struct vm_device * dev, struct ide_channel * channel) {
240     channel->status.val = 0x41; // Error + ready
241     channel->error_reg.val = 0x04; // No idea...
242
243     ide_raise_irq(dev, channel);
244 }
245
246
247
248
249 // Include the ATAPI interface handlers
250 #include "atapi.h"
251
252
253
254
255 static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
256     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
257     struct ide_channel * channel = get_selected_channel(ide, port);
258     struct ide_drive * drive = get_selected_drive(channel);
259
260     if (length != 1) {
261         PrintError("Invalid Write Length on IDE command Port %x\n", port);
262         return -1;
263     }
264
265     PrintDebug("IDE: Writing Command Port %x (val=%x)\n", port, *(uint8_t *)src);
266     
267     channel->cmd_reg = *(uint8_t *)src;
268     
269     switch (channel->cmd_reg) {
270         
271         case 0xa0: // ATAPI Command Packet
272             if (drive->drive_type != IDE_CDROM) {
273                 ide_abort_command(dev, channel);
274             }
275             
276             drive->sector_count = 1;
277
278             channel->status.busy = 0;
279             channel->status.write_fault = 0;
280             channel->status.data_req = 1;
281             channel->status.error = 0;
282
283             // reset the data buffer...
284             drive->transfer_length = ATAPI_PACKET_SIZE;
285             drive->transfer_index = 0;
286
287             break;
288         case 0xa1: // ATAPI Identify Device Packet
289             atapi_identify_device(drive);
290
291             channel->error_reg.val = 0;
292             channel->status.val = 0x58; // ready, data_req, seek_complete
293             
294             ide_raise_irq(dev, channel);
295             break;
296         case 0xec: // Identify Device
297             if (drive->drive_type != IDE_DISK) {
298                 drive_reset(drive);
299
300                 // JRL: Should we abort here?
301                 ide_abort_command(dev, channel);
302             } else {
303                 PrintError("IDE Disks currently not implemented\n");
304                 return -1;
305             }
306             break;
307         default:
308             PrintError("Unimplemented IDE command (%x)\n", channel->cmd_reg);
309             return -1;
310     }
311
312     return length;
313 }
314
315
316 static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
317     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
318     struct ide_channel * channel = get_selected_channel(ide, port);
319     struct ide_drive * drive = get_selected_drive(channel);
320
321     PrintDebug("IDE: Writing Data Port %x (val=%x, len=%d)\n", port, *(uint32_t *)src, length);
322     
323     memcpy(drive->data_buf + drive->transfer_index, src, length);    
324     drive->transfer_index += length;
325
326     // Transfer is complete, dispatch the command
327     if (drive->transfer_index >= drive->transfer_length) {
328         switch (channel->cmd_reg) {
329             case 0x30: // Write Sectors
330                 PrintError("Writing Data not yet implemented\n");
331                 return -1;
332                 
333             case 0xa0: // ATAPI packet command
334                 if (atapi_handle_packet(dev, channel) == -1) {
335                     PrintError("Error handling ATAPI packet\n");
336                     return -1;
337                 }
338                 break;
339             default:
340                 PrintError("Unhandld IDE Command %x\n", channel->cmd_reg);
341                 return -1;
342         }
343     }
344
345     return length;
346 }
347
348
349 static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
350     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
351     struct ide_channel * channel = get_selected_channel(ide, port);
352     struct ide_drive * drive = get_selected_drive(channel);
353     int data_offset = drive->transfer_index % DATA_BUFFER_SIZE;
354
355     PrintDebug("IDE: Reading Data Port %x\n", port);
356
357     if (data_offset == DATA_BUFFER_SIZE) {
358         // check for more data to transfer, if there isn't any then that's a problem...
359         /*
360          *  if (ide_update_buffer(drive) == -1) {
361          *  return -1;
362          *  }
363          */
364         return -1;
365     }
366
367
368     // check for overruns...
369     // We will return the data padded with 0's
370     if (drive->transfer_index + length > drive->transfer_length) {
371         length = drive->transfer_length - drive->transfer_index;
372         memset(dst, 0, length);
373     }
374
375     memcpy(dst, drive->data_buf + data_offset, length);
376
377     drive->transfer_index += length;
378
379     
380     if (drive->transfer_index >= drive->transfer_length) {
381         channel->status.data_req = 0;
382     }
383
384     return length;
385 }
386
387 static int write_port_std(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
388     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
389     struct ide_channel * channel = get_selected_channel(ide, port);
390     struct ide_drive * drive = get_selected_drive(channel);
391             
392     if (length != 1) {
393         PrintError("Invalid Write length on IDE port %x\n", port);
394         return -1;
395     }
396
397     PrintDebug("IDE: Writing Standard Port %x (val=%x)\n", port, *(uint8_t *)src);
398
399
400     switch (port) {
401         // reset and interrupt enable
402         case PRI_CTRL_PORT:
403         case SEC_CTRL_PORT: {
404             struct ide_ctrl_reg * tmp_ctrl = (struct ide_ctrl_reg *)src;
405
406             // only reset channel on a 0->1 reset bit transition
407             if ((!channel->ctrl_reg.soft_reset) && (tmp_ctrl->soft_reset)) {
408                 channel_reset(channel);
409             } else if ((channel->ctrl_reg.soft_reset) && (!tmp_ctrl->soft_reset)) {
410                 channel_reset_complete(channel);
411             }
412
413             channel->ctrl_reg.val = tmp_ctrl->val;          
414             break;
415         }
416         case PRI_FEATURES_PORT:
417         case SEC_FEATURES_PORT:
418             channel->features.val = *(uint8_t *)src;
419             break;
420
421         case PRI_SECT_CNT_PORT:
422         case SEC_SECT_CNT_PORT:
423             drive->sector_count = *(uint8_t *)src;
424             break;
425
426         case PRI_SECT_NUM_PORT:
427         case SEC_SECT_NUM_PORT:
428             drive->sector_num = *(uint8_t *)src;
429
430         case PRI_CYL_LOW_PORT:
431         case SEC_CYL_LOW_PORT:
432             drive->cylinder_low = *(uint8_t *)src;
433             break;
434
435         case PRI_CYL_HIGH_PORT:
436         case SEC_CYL_HIGH_PORT:
437             drive->cylinder_high = *(uint8_t *)src;
438             break;
439
440         case PRI_DRV_SEL_PORT:
441         case SEC_DRV_SEL_PORT: {
442             channel->drive_head.val = *(uint8_t *)src;
443             
444             // make sure the reserved bits are ok..
445             // JRL TODO: check with new ramdisk to make sure this is right...
446             channel->drive_head.val |= 0xa0;
447
448             drive = get_selected_drive(channel);
449
450             // Selecting a non-present device is a no-no
451             if (drive->drive_type == IDE_NONE) {
452                 PrintDebug("Attempting to select a non-present drive\n");
453                 channel->error_reg.abort = 1;
454                 channel->status.error = 1;
455             }
456
457             break;
458         }
459         default:
460             PrintError("IDE: Write to unknown Port %x\n", port);
461             return -1;
462     }
463     return length;
464 }
465
466
467 static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
468     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
469     struct ide_channel * channel = get_selected_channel(ide, port);
470     struct ide_drive * drive = get_selected_drive(channel);
471     
472     if (length != 1) {
473         PrintError("Invalid Read length on IDE port %x\n", port);
474         return -1;
475     }
476
477     PrintDebug("IDE: Reading Standard Port %x\n", port);
478
479
480     if ((port == PRI_ADDR_REG_PORT) ||
481         (port == SEC_ADDR_REG_PORT)) {
482         // unused, return 0xff
483         *(uint8_t *)dst = 0xff;
484         return length;
485     }
486
487
488     // if no drive is present just return 0 + reserved bits
489     if (drive->drive_type == IDE_NONE) {
490         if ((port == PRI_DRV_SEL_PORT) ||
491             (port == SEC_DRV_SEL_PORT)) {
492             *(uint8_t *)dst = 0xa0;
493         } else {
494             *(uint8_t *)dst = 0;
495         }
496
497         return length;
498     }
499
500     switch (port) {
501
502         // This is really the error register.
503         case PRI_FEATURES_PORT:
504         case SEC_FEATURES_PORT:
505             *(uint8_t *)dst = channel->error_reg.val;
506             break;
507             
508         case PRI_SECT_CNT_PORT:
509         case SEC_SECT_CNT_PORT:
510             *(uint8_t *)dst = drive->sector_count;
511             break;
512
513         case PRI_SECT_NUM_PORT:
514         case SEC_SECT_NUM_PORT:
515             *(uint8_t *)dst = drive->sector_num;
516             break;
517
518         case PRI_CYL_LOW_PORT:
519         case SEC_CYL_LOW_PORT:
520             *(uint8_t *)dst = drive->cylinder_low;
521             break;
522
523
524         case PRI_CYL_HIGH_PORT:
525         case SEC_CYL_HIGH_PORT:
526             *(uint8_t *)dst = drive->cylinder_high;
527             break;
528
529         case PRI_DRV_SEL_PORT:
530         case SEC_DRV_SEL_PORT:  // hard disk drive and head register 0x1f6
531             *(uint8_t *)dst = channel->drive_head.val;
532             break;
533
534         case PRI_CTRL_PORT:
535         case SEC_CTRL_PORT:
536         case PRI_CMD_PORT:
537         case SEC_CMD_PORT:
538             // Something about lowering interrupts here....
539             *(uint8_t *)dst = channel->status.val;
540             break;
541
542         default:
543             PrintError("Invalid Port: %x\n", port);
544             return -1;
545     }
546
547     PrintDebug("\tVal=%x\n", *(uint8_t *)dst);
548
549     return length;
550 }
551
552
553
554 static void init_drive(struct ide_drive * drive) {
555
556     drive->sector_count = 0x01;
557     drive->sector_num = 0x01;
558     drive->cylinder = 0x0000;
559
560     drive->drive_type = IDE_NONE;
561
562     memset(drive->model, 0, sizeof(drive->model));
563
564     drive->transfer_index = 0;
565     drive->transfer_length = 0;
566     memset(drive->data_buf, 0, sizeof(drive->data_buf));
567
568     drive->private_data = NULL;
569     drive->cd_ops = NULL;
570 }
571
572 static void init_channel(struct ide_channel * channel) {
573     int i = 0;
574
575     channel->error_reg.val = 0x01;
576     channel->drive_head.val = 0x00;
577     channel->status.val = 0x00;
578     channel->cmd_reg = 0x00;
579     channel->ctrl_reg.val = 0x08;
580
581
582     for (i = 0; i < 2; i++) {
583         init_drive(&(channel->drives[i]));
584     }
585
586 }
587
588 static void init_ide_state(struct ide_internal * ide) {
589     int i;
590
591     for (i = 0; i < 2; i++) {
592         init_channel(&(ide->channels[i]));
593
594         // JRL: this is a terrible hack...
595         ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
596     }
597 }
598
599
600
601 static int init_ide(struct vm_device * dev) {
602     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
603
604     PrintDebug("IDE: Initializing IDE\n");
605
606     init_ide_state(ide);
607
608
609     v3_dev_hook_io(dev, PRI_CTRL_PORT, 
610                    &read_port_std, &write_port_std);
611
612     v3_dev_hook_io(dev, PRI_DATA_PORT, 
613                    &read_data_port, &write_data_port);
614     v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
615                    &read_port_std, &write_port_std);
616     v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
617                    &read_port_std, &write_port_std);
618     v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
619                    &read_port_std, &write_port_std);
620     v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
621                    &read_port_std, &write_port_std);
622     v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
623                    &read_port_std, &write_port_std);
624     v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
625                    &read_port_std, &write_port_std);
626     v3_dev_hook_io(dev, PRI_CMD_PORT, 
627                    &read_port_std, &write_cmd_port);
628
629
630     v3_dev_hook_io(dev, SEC_CTRL_PORT, 
631                    &read_port_std, &write_port_std);
632
633     v3_dev_hook_io(dev, SEC_DATA_PORT, 
634                    &read_data_port, &write_data_port);
635     v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
636                    &read_port_std, &write_port_std);
637     v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
638                    &read_port_std, &write_port_std);
639     v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
640                    &read_port_std, &write_port_std);
641     v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
642                    &read_port_std, &write_port_std);
643     v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
644                    &read_port_std, &write_port_std);
645     v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
646                    &read_port_std, &write_port_std);
647     v3_dev_hook_io(dev, SEC_CMD_PORT, 
648                    &read_port_std, &write_cmd_port);
649   
650   
651
652     v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
653                    &read_port_std, &write_port_std);
654
655     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
656                    &read_port_std, &write_port_std);
657
658     return 0;
659 }
660
661
662 static int deinit_ide(struct vm_device * dev) {
663     // unhook io ports....
664     // deregister from PCI?
665     return 0;
666 }
667
668
669 static struct vm_device_ops dev_ops = {
670     .init = init_ide,
671     .deinit = deinit_ide,
672     .reset = NULL,
673     .start = NULL,
674     .stop = NULL,
675 };
676
677
678 struct vm_device *  v3_create_ide() {
679     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
680     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
681
682     //    ide->pci = pci;
683
684     PrintDebug("IDE: Creating IDE bus x 2\n");
685
686     return device;
687 }
688
689
690
691
692
693 int v3_ide_register_cdrom(struct vm_device * ide_dev, 
694                           uint_t bus_num, 
695                           uint_t drive_num,
696                           char * dev_name, 
697                           struct v3_ide_cd_ops * ops, 
698                           void * private_data) {
699
700     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
701     struct ide_channel * channel = NULL;
702     struct ide_drive * drive = NULL;
703
704     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
705     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
706
707     channel = &(ide->channels[bus_num]);
708     drive = &(channel->drives[drive_num]);
709     
710     if (drive->drive_type != IDE_NONE) {
711         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
712         return -1;
713     }
714
715     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
716
717     while (strlen((char *)(drive->model)) < 40) {
718         strcat((char*)(drive->model), " ");
719     }
720
721
722     drive->drive_type = IDE_CDROM;
723
724     drive->cd_ops = ops;
725
726     drive->private_data = private_data;
727
728     return 0;
729 }
730
731
732 int v3_ide_register_harddisk(struct vm_device * ide_dev, 
733                              uint_t bus_num, 
734                              uint_t drive_num, 
735                              char * dev_name, 
736                              struct v3_ide_hd_ops * ops, 
737                              void * private_data) {
738
739     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
740     struct ide_channel * channel = NULL;
741     struct ide_drive * drive = NULL;
742
743     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
744     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
745
746     channel = &(ide->channels[bus_num]);
747     drive = &(channel->drives[drive_num]);
748     
749     if (drive->drive_type != IDE_NONE) {
750         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
751         return -1;
752     }
753
754     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
755
756     drive->drive_type = IDE_DISK;
757
758     drive->hd_ops = ops;
759
760     drive->private_data = private_data;
761
762     return 0;
763 }