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.


functional DMA reads for IDE disks
[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 <palacios/vm_guest_mem.h>
22 #include <devices/ide.h>
23 #include <devices/pci.h>
24 #include <devices/southbridge.h>
25 #include "ide-types.h"
26 #include "atapi-types.h"
27
28 #ifndef DEBUG_IDE
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33 #define PRI_DEFAULT_IRQ 14
34 #define SEC_DEFAULT_IRQ 15
35
36
37 #define PRI_DATA_PORT         0x1f0
38 #define PRI_FEATURES_PORT     0x1f1
39 #define PRI_SECT_CNT_PORT     0x1f2
40 #define PRI_SECT_NUM_PORT     0x1f3
41 #define PRI_CYL_LOW_PORT      0x1f4
42 #define PRI_CYL_HIGH_PORT     0x1f5
43 #define PRI_DRV_SEL_PORT      0x1f6
44 #define PRI_CMD_PORT          0x1f7
45 #define PRI_CTRL_PORT         0x3f6
46 #define PRI_ADDR_REG_PORT     0x3f7
47
48 #define SEC_DATA_PORT         0x170
49 #define SEC_FEATURES_PORT     0x171
50 #define SEC_SECT_CNT_PORT     0x172
51 #define SEC_SECT_NUM_PORT     0x173
52 #define SEC_CYL_LOW_PORT      0x174
53 #define SEC_CYL_HIGH_PORT     0x175
54 #define SEC_DRV_SEL_PORT      0x176
55 #define SEC_CMD_PORT          0x177
56 #define SEC_CTRL_PORT         0x376
57 #define SEC_ADDR_REG_PORT     0x377
58
59
60 #define PRI_DEFAULT_DMA_PORT 0xc000
61 #define SEC_DEFAULT_DMA_PORT 0xc008
62
63 #define DATA_BUFFER_SIZE 2048
64
65 static const char * ide_pri_port_strs[] = {"PRI_DATA", "PRI_FEATURES", "PRI_SECT_CNT", "PRI_SECT_NUM", 
66                                           "PRI_CYL_LOW", "PRI_CYL_HIGH", "PRI_DRV_SEL", "PRI_CMD",
67                                            "PRI_CTRL", "PRI_ADDR_REG"};
68
69
70 static const char * ide_sec_port_strs[] = {"SEC_DATA", "SEC_FEATURES", "SEC_SECT_CNT", "SEC_SECT_NUM", 
71                                           "SEC_CYL_LOW", "SEC_CYL_HIGH", "SEC_DRV_SEL", "SEC_CMD",
72                                            "SEC_CTRL", "SEC_ADDR_REG"};
73
74 static const char * ide_dma_port_strs[] = {"DMA_CMD", NULL, "DMA_STATUS", NULL,
75                                            "DMA_PRD0", "DMA_PRD1", "DMA_PRD2", "DMA_PRD3"};
76
77
78
79 static inline const char * io_port_to_str(uint16_t port) {
80     if ((port >= PRI_DATA_PORT) && (port <= PRI_CMD_PORT)) {
81         return ide_pri_port_strs[port - PRI_DATA_PORT];
82     } else if ((port >= SEC_DATA_PORT) && (port <= SEC_CMD_PORT)) {
83         return ide_sec_port_strs[port - SEC_DATA_PORT];
84     } else if ((port == PRI_CTRL_PORT) || (port == PRI_ADDR_REG_PORT)) {
85         return ide_pri_port_strs[port - PRI_CTRL_PORT + 8];
86     } else if ((port == SEC_CTRL_PORT) || (port == SEC_ADDR_REG_PORT)) {
87         return ide_sec_port_strs[port - SEC_CTRL_PORT + 8];
88     } 
89     return NULL;
90 }
91
92
93 static inline const char * dma_port_to_str(uint16_t port) {
94     return ide_dma_port_strs[port & 0x7];
95 }
96
97
98 static const char * ide_dev_type_strs[] = {"NONE", "HARDDISK", "CDROM" };
99
100
101 static inline const char * device_type_to_str(v3_ide_dev_type_t type) {
102     if (type > 2) {
103         return NULL;
104     }
105
106     return ide_dev_type_strs[type];
107 }
108
109
110
111 struct ide_cd_state {
112     struct atapi_sense_data sense;
113
114     uint8_t atapi_cmd;
115     struct atapi_error_recovery err_recovery;
116 };
117
118 struct ide_hd_state {
119     int accessed;
120
121     /* this is the multiple sector transfer size as configured for read/write multiple sectors*/
122     uint_t mult_sector_num;
123
124     /* This is the current op sector size:
125      * for multiple sector ops this equals mult_sector_num
126      * for standard ops this equals 1
127      */
128     uint_t cur_sector_num;
129 };
130
131 struct ide_drive {
132     // Command Registers
133
134     v3_ide_dev_type_t drive_type;
135
136     union {
137         struct v3_ide_cd_ops * cd_ops;
138         struct v3_ide_hd_ops * hd_ops;
139     };
140
141
142     union {
143         struct ide_cd_state cd_state;
144         struct ide_hd_state hd_state;
145     };
146
147     char model[41];
148
149     // Where we are in the data transfer
150     uint_t transfer_index;
151
152     // the length of a transfer
153     // calculated for easy access
154     uint_t transfer_length;
155
156     uint64_t current_lba;
157
158     // We have a local data buffer that we use for IO port accesses
159     uint8_t data_buf[DATA_BUFFER_SIZE];
160
161
162
163     uint32_t num_cylinders;
164     uint32_t num_heads;
165     uint32_t num_sectors;
166
167     void * private_data;
168     
169     union {
170         uint8_t sector_count;             // 0x1f2,0x172
171         struct atapi_irq_flags irq_flags;
172     } __attribute__((packed));
173
174     union {
175         uint8_t sector_num;               // 0x1f3,0x173
176         uint8_t lba0;
177     } __attribute__((packed));
178
179     union {
180         uint16_t cylinder;
181         uint16_t lba12;
182         
183         struct {
184             uint8_t cylinder_low;       // 0x1f4,0x174
185             uint8_t cylinder_high;      // 0x1f5,0x175
186         } __attribute__((packed));
187         
188         struct {
189             uint8_t lba1;
190             uint8_t lba2;
191         } __attribute__((packed));
192         
193         
194         // The transfer length requested by the CPU 
195         uint16_t req_len;
196     } __attribute__((packed));
197
198 };
199
200
201
202 struct ide_channel {
203     struct ide_drive drives[2];
204
205     // Command Registers
206     struct ide_error_reg error_reg;     // [read] 0x1f1,0x171
207
208     struct ide_features_reg features;
209
210     struct ide_drive_head_reg drive_head; // 0x1f6,0x176
211
212     struct ide_status_reg status;       // [read] 0x1f7,0x177
213     uint8_t cmd_reg;                // [write] 0x1f7,0x177
214
215     int irq; // this is temporary until we add PCI support
216
217     // Control Registers
218     struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
219
220     struct ide_dma_cmd_reg dma_cmd;
221     struct ide_dma_status_reg dma_status;
222     uint32_t dma_prd_addr;
223     uint_t dma_tbl_index;
224 };
225
226
227
228 struct ide_internal {
229     struct ide_channel channels[2];
230
231     struct v3_southbridge * southbridge;
232     struct vm_device * pci_bus;
233
234     struct pci_device * ide_pci;
235 };
236
237
238
239
240
241 /* Utility functions */
242
243 static inline uint16_t be_to_le_16(const uint16_t val) {
244     uint8_t * buf = (uint8_t *)&val;
245     return (buf[0] << 8) | (buf[1]) ;
246 }
247
248 static inline uint16_t le_to_be_16(const uint16_t val) {
249     return be_to_le_16(val);
250 }
251
252
253 static inline uint32_t be_to_le_32(const uint32_t val) {
254     uint8_t * buf = (uint8_t *)&val;
255     return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
256 }
257
258 static inline uint32_t le_to_be_32(const uint32_t val) {
259     return be_to_le_32(val);
260 }
261
262
263 static inline int get_channel_index(ushort_t port) {
264     if (((port & 0xfff8) == 0x1f0) ||
265         ((port & 0xfffe) == 0x3f6) || 
266         ((port & 0xfff8) == 0xc000)) {
267         return 0;
268     } else if (((port & 0xfff8) == 0x170) ||
269                ((port & 0xfffe) == 0x376) ||
270                ((port & 0xfff8) == 0xc008)) {
271         return 1;
272     }
273
274     return -1;
275 }
276
277 static inline struct ide_channel * get_selected_channel(struct ide_internal * ide, ushort_t port) {
278     int channel_idx = get_channel_index(port);    
279     return &(ide->channels[channel_idx]);
280 }
281
282 static inline struct ide_drive * get_selected_drive(struct ide_channel * channel) {
283     return &(channel->drives[channel->drive_head.drive_sel]);
284 }
285
286
287 static inline int is_lba_enabled(struct ide_channel * channel) {
288     return channel->drive_head.lba_mode;
289 }
290
291
292 /* Drive Commands */
293 static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
294     if (channel->ctrl_reg.irq_disable == 0) {
295         PrintDebug("Raising IDE Interrupt %d\n", channel->irq);
296         channel->dma_status.int_gen = 1;
297         v3_raise_irq(dev->vm, channel->irq);
298     }
299 }
300
301
302 static void drive_reset(struct ide_drive * drive) {
303     drive->sector_count = 0x01;
304     drive->sector_num = 0x01;
305
306     PrintDebug("Resetting drive %s\n", drive->model);
307     
308     if (drive->drive_type == IDE_CDROM) {
309         drive->cylinder = 0xeb14;
310     } else {
311         drive->cylinder = 0x0000;
312         //drive->hd_state.accessed = 0;
313     }
314
315
316     memset(drive->data_buf, 0, sizeof(drive->data_buf));
317     drive->transfer_index = 0;
318
319     // Send the reset signal to the connected device callbacks
320     //     channel->drives[0].reset();
321     //    channel->drives[1].reset();
322 }
323
324 static void channel_reset(struct ide_channel * channel) {
325     
326     // set busy and seek complete flags
327     channel->status.val = 0x90;
328
329     // Clear errors
330     channel->error_reg.val = 0x01;
331
332     // clear commands
333     channel->cmd_reg = 0x00;
334
335     channel->ctrl_reg.irq_disable = 0;
336 }
337
338 static void channel_reset_complete(struct ide_channel * channel) {
339     channel->status.busy = 0;
340     channel->status.ready = 1;
341
342     channel->drive_head.head_num = 0;    
343     
344     drive_reset(&(channel->drives[0]));
345     drive_reset(&(channel->drives[1]));
346 }
347
348
349 static void ide_abort_command(struct vm_device * dev, struct ide_channel * channel) {
350     channel->status.val = 0x41; // Error + ready
351     channel->error_reg.val = 0x04; // No idea...
352
353     ide_raise_irq(dev, channel);
354 }
355
356
357
358
359
360
361 /* ATAPI functions */
362 #include "atapi.h"
363
364 /* ATA functions */
365 #include "ata.h"
366
367
368
369 /* IO Operations */
370 static int dma_read(struct vm_device * dev, struct ide_channel * channel) {
371     struct ide_drive * drive = get_selected_drive(channel);
372     // This is at top level scope to do the EOT test at the end
373     struct ide_dma_prd prd_entry;
374
375     // Read in the data buffer....
376     // Read a sector/block at a time until the prd entry is full.
377
378     if (drive->drive_type == IDE_DISK) {
379         uint_t bytes_left = drive->transfer_length;
380
381         // Loop through the disk data
382         while (bytes_left > 0) {
383
384             uint32_t prd_entry_addr =  channel->dma_prd_addr + (sizeof(struct ide_dma_prd) * channel->dma_tbl_index);
385             uint_t prd_bytes_left = 0;
386             uint_t prd_offset = 0;
387             int ret;
388             
389             PrintDebug("PRD table address = %x\n", channel->dma_prd_addr);
390             
391             ret = read_guest_pa_memory(dev->vm, prd_entry_addr, sizeof(struct ide_dma_prd), (void *)&prd_entry);
392             
393             if (ret != sizeof(struct ide_dma_prd)) {
394                 PrintError("Could not read PRD\n");
395                 return -1;
396             }
397             
398             PrintDebug("PRD Addr: %x, PDR Len: %d, EOT: %d\n", prd_entry.base_addr, prd_entry.size, prd_entry.end_of_table);
399             
400             // loop through the PRD data....
401             
402             prd_bytes_left = prd_entry.size;
403
404
405             while (prd_bytes_left > 0) {
406                 uint_t bytes_to_write = (prd_bytes_left > IDE_SECTOR_SIZE) ? IDE_SECTOR_SIZE : prd_bytes_left;
407
408
409                 if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
410                     PrintError("Failed to read next disk sector\n");
411                     return -1;
412                 }
413
414                 drive->current_lba++;
415                 
416                 ret = write_guest_pa_memory(dev->vm, prd_entry.base_addr + prd_offset, bytes_to_write, drive->data_buf); 
417                 
418                 if (ret != bytes_to_write) {
419                     PrintError("Failed to copy data into guest memory... (ret=%d)\n", ret);
420                     return -1;
421                 }
422                 
423                 drive->transfer_index += ret;
424                 prd_bytes_left -= ret;
425                 prd_offset += ret;
426                 bytes_left -= ret;
427             }
428             
429             channel->dma_tbl_index++;   
430
431             if (drive->transfer_index % IDE_SECTOR_SIZE) {
432                 PrintError("We currently don't handle sectors that span PRD descriptors\n");
433                 return -1;
434             }
435
436             if ((prd_entry.end_of_table == 1) && (bytes_left > 0)) {
437                 PrintError("DMA table not large enough for data transfer...\n");
438                 return -1;
439             }
440
441         }
442
443     } else if (drive->drive_type == IDE_CDROM) {
444         PrintError("CDROM DMA not supported\n");
445         return -1;
446     }
447
448     /*
449       drive->irq_flags.io_dir = 1;
450       drive->irq_flags.c_d = 1;
451       drive->irq_flags.rel = 0;
452     */
453
454
455     // Update to the next PRD entry
456
457     // set DMA status
458
459     if (prd_entry.end_of_table) {
460         channel->status.busy = 0;
461         channel->status.ready = 1;
462         channel->status.data_req = 0;
463         channel->status.error = 0;
464         channel->status.seek_complete = 1;
465
466         channel->dma_status.active = 0;
467         channel->dma_status.err = 0;
468     }
469
470     ide_raise_irq(dev, channel);
471
472     return 0;
473 }
474
475
476 static int dma_write(struct vm_device * dev, struct ide_channel * channel) {
477     // unsupported
478     PrintError("DMA writes currently not supported\n");
479     return -1;
480 }
481
482
483
484 #define DMA_CMD_PORT      0x00
485 #define DMA_STATUS_PORT   0x02
486 #define DMA_PRD_PORT0     0x04
487 #define DMA_PRD_PORT1     0x05
488 #define DMA_PRD_PORT2     0x06
489 #define DMA_PRD_PORT3     0x07
490
491 #define DMA_CHANNEL_FLAG  0x08
492
493 static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
494     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
495     uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
496     uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
497     struct ide_channel * channel = &(ide->channels[channel_flag]);
498
499     PrintDebug("IDE: Writing DMA Port %x (%s) (val=%x) (len=%d) (channel=%d)\n", 
500                port, dma_port_to_str(port_offset), *(uint32_t *)src, length, channel_flag);
501
502     switch (port_offset) {
503         case DMA_CMD_PORT:
504             channel->dma_cmd.val = *(uint8_t *)src;
505
506             if (channel->dma_cmd.start == 0) {
507                 channel->dma_tbl_index = 0;
508             } else {
509                 channel->dma_status.active = 1;
510
511                 if (channel->dma_cmd.read == 1) {
512                     // DMA Read
513                     if (dma_read(dev, channel) == -1) {
514                         PrintError("Failed DMA Read\n");
515                         return -1;
516                     }
517                 } else {
518                     // DMA write
519                     if (dma_write(dev, channel) == -1) {
520                         PrintError("Failed DMA Write\n");
521                         return -1;
522                     }
523                 }
524
525                 channel->dma_cmd.val &= 0x09;
526             }
527
528             break;
529             
530         case DMA_STATUS_PORT: {
531             uint8_t val = *(uint8_t *)src;
532
533             if (length != 1) {
534                 PrintError("Invalid read length for DMA status port\n");
535                 return -1;
536             }
537
538             // weirdness
539             channel->dma_status.val = ((val & 0x60) | 
540                                        (channel->dma_status.val & 0x01) |
541                                        (channel->dma_status.val & ~val & 0x06));
542
543             break;
544         }           
545         case DMA_PRD_PORT0:
546         case DMA_PRD_PORT1:
547         case DMA_PRD_PORT2:
548         case DMA_PRD_PORT3: {
549             uint_t addr_index = port_offset & 0x3;
550             uint8_t * addr_buf = (uint8_t *)&(channel->dma_prd_addr);
551             int i = 0;
552
553             if (addr_index + length > 4) {
554                 PrintError("DMA Port space overrun port=%x len=%d\n", port_offset, length);
555                 return -1;
556             }
557
558             for (i = 0; i < length; i++) {
559                 addr_buf[addr_index + i] = *((uint8_t *)src + i);
560             }
561
562             PrintDebug("Writing PRD Port %x (val=%x)\n", port_offset, channel->dma_prd_addr);
563
564             break;
565         }
566         default:
567             PrintError("IDE: Invalid DMA Port (%s)\n", dma_port_to_str(port_offset));
568             return -1;
569     }
570
571     return length;
572 }
573
574
575 static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
576     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
577     uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
578     uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
579     struct ide_channel * channel = &(ide->channels[channel_flag]);
580
581     PrintDebug("Reading DMA port %d (%x) (channel=%d)\n", port, port, channel_flag);
582
583     switch (port_offset) {
584         case DMA_CMD_PORT:
585             *(uint8_t *)dst = channel->dma_cmd.val;
586             break;
587
588         case DMA_STATUS_PORT:
589             if (length != 1) {
590                 PrintError("Invalid read length for DMA status port\n");
591                 return -1;
592             }
593
594             *(uint8_t *)dst = channel->dma_status.val;
595             break;
596
597         case DMA_PRD_PORT0:
598         case DMA_PRD_PORT1:
599         case DMA_PRD_PORT2:
600         case DMA_PRD_PORT3: {
601             uint_t addr_index = port_offset & 0x3;
602             uint8_t * addr_buf = (uint8_t *)&(channel->dma_prd_addr);
603             int i = 0;
604
605             if (addr_index + length > 4) {
606                 PrintError("DMA Port space overrun port=%x len=%d\n", port_offset, length);
607                 return -1;
608             }
609
610             for (i = 0; i < length; i++) {
611                 *((uint8_t *)dst + i) = addr_buf[addr_index + i];
612             }
613
614             break;
615         }
616         default:
617             PrintError("IDE: Invalid DMA Port (%s)\n", dma_port_to_str(port_offset));
618             return -1;
619     }
620
621     PrintDebug("\tval=%x (len=%d)\n", *(uint32_t *)dst, length);
622
623     return length;
624 }
625
626
627
628 static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
629     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
630     struct ide_channel * channel = get_selected_channel(ide, port);
631     struct ide_drive * drive = get_selected_drive(channel);
632
633     if (length != 1) {
634         PrintError("Invalid Write Length on IDE command Port %x\n", port);
635         return -1;
636     }
637
638     PrintDebug("IDE: Writing Command Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
639     
640     channel->cmd_reg = *(uint8_t *)src;
641     
642     switch (channel->cmd_reg) {
643
644         case 0xa1: // ATAPI Identify Device Packet
645             if (drive->drive_type != IDE_CDROM) {
646                 drive_reset(drive);
647
648                 // JRL: Should we abort here?
649                 ide_abort_command(dev, channel);
650             } else {
651                 
652                 atapi_identify_device(drive);
653                 
654                 channel->error_reg.val = 0;
655                 channel->status.val = 0x58; // ready, data_req, seek_complete
656             
657                 ide_raise_irq(dev, channel);
658             }
659             break;
660         case 0xec: // Identify Device
661             if (drive->drive_type != IDE_DISK) {
662                 drive_reset(drive);
663
664                 // JRL: Should we abort here?
665                 ide_abort_command(dev, channel);
666             } else {
667                 ata_identify_device(drive);
668
669                 channel->error_reg.val = 0;
670                 channel->status.val = 0x58;
671
672                 ide_raise_irq(dev, channel);
673             }
674             break;
675
676         case 0xa0: // ATAPI Command Packet
677             if (drive->drive_type != IDE_CDROM) {
678                 ide_abort_command(dev, channel);
679             }
680             
681             drive->sector_count = 1;
682
683             channel->status.busy = 0;
684             channel->status.write_fault = 0;
685             channel->status.data_req = 1;
686             channel->status.error = 0;
687
688             // reset the data buffer...
689             drive->transfer_length = ATAPI_PACKET_SIZE;
690             drive->transfer_index = 0;
691
692             break;
693
694         case 0x20: // Read Sectors with Retry
695         case 0x21: // Read Sectors without Retry
696             drive->hd_state.cur_sector_num = 1;
697
698             if (ata_read_sectors(dev, channel) == -1) {
699                 PrintError("Error reading sectors\n");
700                 return -1;
701             }
702             break;
703
704         case 0x24: // Read Sectors Extended
705             drive->hd_state.cur_sector_num = 1;
706
707             if (ata_read_sectors_ext(dev, channel) == -1) {
708                 PrintError("Error reading extended sectors\n");
709                 return -1;
710             }
711             break;
712
713         case 0xc8: // Read DMA with retry
714         case 0xc9: { // Read DMA
715             uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
716
717             if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) {
718                 ide_abort_command(dev, channel);
719                 return 0;
720             }
721             
722             drive->hd_state.cur_sector_num = 1;
723             
724             drive->transfer_length = sect_cnt * IDE_SECTOR_SIZE;
725             drive->transfer_index = 0;
726
727             if (channel->dma_status.active == 1) {
728                 // DMA Read
729                 if (dma_read(dev, channel) == -1) {
730                     PrintError("Failed DMA Read\n");
731                     return -1;
732                 }
733             }
734             break;
735         }
736         case 0xef: // Set Features
737             // Prior to this the features register has been written to. 
738             // This command tells the drive to check if the new value is supported (the value is drive specific)
739             // Common is that bit0=DMA enable
740             // If valid the drive raises an interrupt, if not it aborts.
741
742             // Do some checking here...
743
744             channel->status.busy = 0;
745             channel->status.write_fault = 0;
746             channel->status.error = 0;
747             channel->status.ready = 1;
748             channel->status.seek_complete = 1;
749             
750             ide_raise_irq(dev, channel);
751             break;
752
753         case 0x91:  // Initialize Drive Parameters
754         case 0x10:  // recalibrate?
755             channel->status.error = 0;
756             channel->status.ready = 1;
757             channel->status.seek_complete = 1;
758             ide_raise_irq(dev, channel);
759             break;
760         case 0xc6: { // Set multiple mode (IDE Block mode) 
761             // This makes the drive transfer multiple sectors before generating an interrupt
762             uint32_t tmp_sect_num = drive->sector_num; // GCC SUCKS
763
764             if (tmp_sect_num > MAX_MULT_SECTORS) {
765                 ide_abort_command(dev, channel);
766                 break;
767             }
768
769             if (drive->sector_count == 0) {
770                 drive->hd_state.mult_sector_num= 1;
771             } else {
772                 drive->hd_state.mult_sector_num = drive->sector_count;
773             }
774
775             channel->status.ready = 1;
776             channel->status.error = 0;
777
778             ide_raise_irq(dev, channel);
779
780             break;
781         }
782         case 0xc4:  // read multiple sectors
783             drive->hd_state.cur_sector_num = drive->hd_state.mult_sector_num;
784         default:
785             PrintError("Unimplemented IDE command (%x)\n", channel->cmd_reg);
786             return -1;
787     }
788
789     return length;
790 }
791
792
793 static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
794     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
795     struct ide_channel * channel = get_selected_channel(ide, port);
796     struct ide_drive * drive = get_selected_drive(channel);
797
798     //    PrintDebug("IDE: Writing Data Port %x (val=%x, len=%d)\n", 
799     //         port, *(uint32_t *)src, length);
800     
801     memcpy(drive->data_buf + drive->transfer_index, src, length);    
802     drive->transfer_index += length;
803
804     // Transfer is complete, dispatch the command
805     if (drive->transfer_index >= drive->transfer_length) {
806         switch (channel->cmd_reg) {
807             case 0x30: // Write Sectors
808                 PrintError("Writing Data not yet implemented\n");
809                 return -1;
810                 
811             case 0xa0: // ATAPI packet command
812                 if (atapi_handle_packet(dev, channel) == -1) {
813                     PrintError("Error handling ATAPI packet\n");
814                     return -1;
815                 }
816                 break;
817             default:
818                 PrintError("Unhandld IDE Command %x\n", channel->cmd_reg);
819                 return -1;
820         }
821     }
822
823     return length;
824 }
825
826
827 static int read_hd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
828     struct ide_drive * drive = get_selected_drive(channel);
829     int data_offset = drive->transfer_index % IDE_SECTOR_SIZE;
830
831
832
833     if (drive->transfer_index >= drive->transfer_length) {
834         PrintError("Buffer overrun... (xfer_len=%d) (cur_idx=%x) (post_idx=%d)\n",
835                    drive->transfer_length, drive->transfer_index,
836                    drive->transfer_index + length);
837         return -1;
838     }
839
840     
841     if ((data_offset == 0) && (drive->transfer_index > 0)) {
842         drive->current_lba++;
843
844         if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
845             PrintError("Could not read next disk sector\n");
846             return -1;
847         }
848     }
849
850     /*
851       PrintDebug("Reading HD Data (Val=%x), (len=%d) (offset=%d)\n", 
852       *(uint32_t *)(drive->data_buf + data_offset), 
853       length, data_offset);
854     */
855     memcpy(dst, drive->data_buf + data_offset, length);
856
857     drive->transfer_index += length;
858
859
860     /* This is the trigger for interrupt injection.
861      * For read single sector commands we interrupt after every sector
862      * For multi sector reads we interrupt only at end of the cluster size (mult_sector_num)
863      * cur_sector_num is configured depending on the operation we are currently running
864      * We also trigger an interrupt if this is the last byte to transfer, regardless of sector count
865      */
866     if (((drive->transfer_index % (IDE_SECTOR_SIZE * drive->hd_state.cur_sector_num)) == 0) || 
867         (drive->transfer_index == drive->transfer_length)) {
868         if (drive->transfer_index < drive->transfer_length) {
869             // An increment is complete, but there is still more data to be transferred...
870             PrintDebug("Integral Complete, still transferring more sectors\n");
871             channel->status.data_req = 1;
872
873             drive->irq_flags.c_d = 0;
874         } else {
875             PrintDebug("Final Sector Transferred\n");
876             // This was the final read of the request
877             channel->status.data_req = 0;
878
879             
880             drive->irq_flags.c_d = 1;
881             drive->irq_flags.rel = 0;
882         }
883
884         channel->status.ready = 1;
885         drive->irq_flags.io_dir = 1;
886         channel->status.busy = 0;
887
888         ide_raise_irq(dev, channel);
889     }
890
891
892     return length;
893 }
894
895
896
897 static int read_cd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
898     struct ide_drive * drive = get_selected_drive(channel);
899     int data_offset = drive->transfer_index % ATAPI_BLOCK_SIZE;
900     int req_offset = drive->transfer_index % drive->req_len;
901     
902     if (drive->cd_state.atapi_cmd != 0x28) {
903         PrintDebug("IDE: Reading CD Data (len=%d) (req_len=%d)\n", length, drive->req_len);
904     }
905
906     if (drive->transfer_index >= drive->transfer_length) {
907         PrintError("Buffer Overrun... (xfer_len=%d) (cur_idx=%d) (post_idx=%d)\n", 
908                    drive->transfer_length, drive->transfer_index, 
909                    drive->transfer_index + length);
910         return -1;
911     }
912
913
914
915     if ((data_offset == 0) && (drive->transfer_index > 0)) {
916         if (atapi_update_data_buf(dev, channel) == -1) {
917             PrintError("Could not update CDROM data buffer\n");
918             return -1;
919         }
920     }
921
922     memcpy(dst, drive->data_buf + data_offset, length);
923     
924     drive->transfer_index += length;
925
926
927     // Should the req_offset be recalculated here?????
928     if ((req_offset == 0) && (drive->transfer_index > 0)) {
929         if (drive->transfer_index < drive->transfer_length) {
930             // An increment is complete, but there is still more data to be transferred...
931             
932             channel->status.data_req = 1;
933
934             drive->irq_flags.c_d = 0;
935
936             // Update the request length in the cylinder regs
937             if (atapi_update_req_len(dev, channel, drive->transfer_length - drive->transfer_index) == -1) {
938                 PrintError("Could not update request length after completed increment\n");
939                 return -1;
940             }
941         } else {
942             // This was the final read of the request
943             channel->status.data_req = 0;
944             channel->status.ready = 1;
945             
946             drive->irq_flags.c_d = 1;
947             drive->irq_flags.rel = 0;
948         }
949
950         drive->irq_flags.io_dir = 1;
951         channel->status.busy = 0;
952
953         ide_raise_irq(dev, channel);
954     }
955
956     return length;
957 }
958
959
960 static int read_drive_id(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
961     struct ide_drive * drive = get_selected_drive(channel);
962
963     channel->status.busy = 0;
964     channel->status.ready = 1;
965     channel->status.write_fault = 0;
966     channel->status.seek_complete = 1;
967     channel->status.corrected = 0;
968     channel->status.error = 0;
969                 
970     
971     memcpy(dst, drive->data_buf + drive->transfer_index, length);
972     drive->transfer_index += length;
973     
974     if (drive->transfer_index >= drive->transfer_length) {
975         channel->status.data_req = 0;
976     }
977     
978     return length;
979 }
980
981
982 static int ide_read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
983     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
984     struct ide_channel * channel = get_selected_channel(ide, port);
985     struct ide_drive * drive = get_selected_drive(channel);
986
987     //    PrintDebug("IDE: Reading Data Port %x (len=%d)\n", port, length);
988
989     if ((channel->cmd_reg == 0xec) ||
990         (channel->cmd_reg == 0xa1)) {
991         return read_drive_id((uint8_t *)dst, length, dev, channel);
992     }
993
994     if (drive->drive_type == IDE_CDROM) {
995         if (read_cd_data((uint8_t *)dst, length, dev, channel) == -1) {
996             PrintError("IDE: Could not read CD Data\n");
997             return -1;
998         }
999     } else if (drive->drive_type == IDE_DISK) {
1000         if (read_hd_data((uint8_t *)dst, length, dev, channel) == -1) {
1001             PrintError("IDE: Could not read HD Data\n");
1002             return -1;
1003         }
1004     } else {
1005         memset((uint8_t *)dst, 0, length);
1006     }
1007
1008     return length;
1009 }
1010
1011 static int write_port_std(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
1012     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
1013     struct ide_channel * channel = get_selected_channel(ide, port);
1014     struct ide_drive * drive = get_selected_drive(channel);
1015             
1016     if (length != 1) {
1017         PrintError("Invalid Write length on IDE port %x\n", port);
1018         return -1;
1019     }
1020
1021     PrintDebug("IDE: Writing Standard Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
1022
1023     switch (port) {
1024         // reset and interrupt enable
1025         case PRI_CTRL_PORT:
1026         case SEC_CTRL_PORT: {
1027             struct ide_ctrl_reg * tmp_ctrl = (struct ide_ctrl_reg *)src;
1028
1029             // only reset channel on a 0->1 reset bit transition
1030             if ((!channel->ctrl_reg.soft_reset) && (tmp_ctrl->soft_reset)) {
1031                 channel_reset(channel);
1032             } else if ((channel->ctrl_reg.soft_reset) && (!tmp_ctrl->soft_reset)) {
1033                 channel_reset_complete(channel);
1034             }
1035
1036             channel->ctrl_reg.val = tmp_ctrl->val;          
1037             break;
1038         }
1039         case PRI_FEATURES_PORT:
1040         case SEC_FEATURES_PORT:
1041             channel->features.val = *(uint8_t *)src;
1042             break;
1043
1044         case PRI_SECT_CNT_PORT:
1045         case SEC_SECT_CNT_PORT:
1046             channel->drives[0].sector_count = *(uint8_t *)src;
1047             channel->drives[1].sector_count = *(uint8_t *)src;
1048             break;
1049
1050         case PRI_SECT_NUM_PORT:
1051         case SEC_SECT_NUM_PORT:
1052             channel->drives[0].sector_num = *(uint8_t *)src;
1053             channel->drives[1].sector_num = *(uint8_t *)src;
1054             break;
1055         case PRI_CYL_LOW_PORT:
1056         case SEC_CYL_LOW_PORT:
1057             channel->drives[0].cylinder_low = *(uint8_t *)src;
1058             channel->drives[1].cylinder_low = *(uint8_t *)src;
1059             break;
1060
1061         case PRI_CYL_HIGH_PORT:
1062         case SEC_CYL_HIGH_PORT:
1063             channel->drives[0].cylinder_high = *(uint8_t *)src;
1064             channel->drives[1].cylinder_high = *(uint8_t *)src;
1065             break;
1066
1067         case PRI_DRV_SEL_PORT:
1068         case SEC_DRV_SEL_PORT: {
1069             channel->drive_head.val = *(uint8_t *)src;
1070             
1071             // make sure the reserved bits are ok..
1072             // JRL TODO: check with new ramdisk to make sure this is right...
1073             channel->drive_head.val |= 0xa0;
1074
1075             drive = get_selected_drive(channel);
1076
1077             // Selecting a non-present device is a no-no
1078             if (drive->drive_type == IDE_NONE) {
1079                 PrintDebug("Attempting to select a non-present drive\n");
1080                 channel->error_reg.abort = 1;
1081                 channel->status.error = 1;
1082             }
1083
1084             break;
1085         }
1086         default:
1087             PrintError("IDE: Write to unknown Port %x\n", port);
1088             return -1;
1089     }
1090     return length;
1091 }
1092
1093
1094 static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
1095     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
1096     struct ide_channel * channel = get_selected_channel(ide, port);
1097     struct ide_drive * drive = get_selected_drive(channel);
1098     
1099     if (length != 1) {
1100         PrintError("Invalid Read length on IDE port %x\n", port);
1101         return -1;
1102     }
1103     
1104     PrintDebug("IDE: Reading Standard Port %x (%s)\n", port, io_port_to_str(port));
1105
1106     if ((port == PRI_ADDR_REG_PORT) ||
1107         (port == SEC_ADDR_REG_PORT)) {
1108         // unused, return 0xff
1109         *(uint8_t *)dst = 0xff;
1110         return length;
1111     }
1112
1113
1114     // if no drive is present just return 0 + reserved bits
1115     if (drive->drive_type == IDE_NONE) {
1116         if ((port == PRI_DRV_SEL_PORT) ||
1117             (port == SEC_DRV_SEL_PORT)) {
1118             *(uint8_t *)dst = 0xa0;
1119         } else {
1120             *(uint8_t *)dst = 0;
1121         }
1122
1123         return length;
1124     }
1125
1126     switch (port) {
1127
1128         // This is really the error register.
1129         case PRI_FEATURES_PORT:
1130         case SEC_FEATURES_PORT:
1131             *(uint8_t *)dst = channel->error_reg.val;
1132             break;
1133             
1134         case PRI_SECT_CNT_PORT:
1135         case SEC_SECT_CNT_PORT:
1136             *(uint8_t *)dst = drive->sector_count;
1137             break;
1138
1139         case PRI_SECT_NUM_PORT:
1140         case SEC_SECT_NUM_PORT:
1141             *(uint8_t *)dst = drive->sector_num;
1142             break;
1143
1144         case PRI_CYL_LOW_PORT:
1145         case SEC_CYL_LOW_PORT:
1146             *(uint8_t *)dst = drive->cylinder_low;
1147             break;
1148
1149
1150         case PRI_CYL_HIGH_PORT:
1151         case SEC_CYL_HIGH_PORT:
1152             *(uint8_t *)dst = drive->cylinder_high;
1153             break;
1154
1155         case PRI_DRV_SEL_PORT:
1156         case SEC_DRV_SEL_PORT:  // hard disk drive and head register 0x1f6
1157             *(uint8_t *)dst = channel->drive_head.val;
1158             break;
1159
1160         case PRI_CTRL_PORT:
1161         case SEC_CTRL_PORT:
1162         case PRI_CMD_PORT:
1163         case SEC_CMD_PORT:
1164             // Something about lowering interrupts here....
1165             *(uint8_t *)dst = channel->status.val;
1166             break;
1167
1168         default:
1169             PrintError("Invalid Port: %x\n", port);
1170             return -1;
1171     }
1172
1173     PrintDebug("\tVal=%x\n", *(uint8_t *)dst);
1174
1175     return length;
1176 }
1177
1178
1179
1180 static void init_drive(struct ide_drive * drive) {
1181
1182     drive->sector_count = 0x01;
1183     drive->sector_num = 0x01;
1184     drive->cylinder = 0x0000;
1185
1186     drive->drive_type = IDE_NONE;
1187
1188     memset(drive->model, 0, sizeof(drive->model));
1189
1190     drive->transfer_index = 0;
1191     drive->transfer_length = 0;
1192     memset(drive->data_buf, 0, sizeof(drive->data_buf));
1193
1194     drive->num_cylinders = 0;
1195     drive->num_heads = 0;
1196     drive->num_sectors = 0;
1197     
1198
1199     drive->private_data = NULL;
1200     drive->cd_ops = NULL;
1201 }
1202
1203 static void init_channel(struct ide_channel * channel) {
1204     int i = 0;
1205
1206     channel->error_reg.val = 0x01;
1207     channel->drive_head.val = 0x00;
1208     channel->status.val = 0x00;
1209     channel->cmd_reg = 0x00;
1210     channel->ctrl_reg.val = 0x08;
1211
1212
1213     channel->dma_cmd.val = 0;
1214     channel->dma_status.val = 0;
1215     channel->dma_prd_addr = 0;
1216     channel->dma_tbl_index = 0;
1217
1218     for (i = 0; i < 2; i++) {
1219         init_drive(&(channel->drives[i]));
1220     }
1221
1222 }
1223
1224
1225 static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) {
1226     PrintDebug("PCI Config Update\n");
1227     PrintDebug("\t\tInterupt register (Dev=%s), irq=%d\n", pci_dev->name, pci_dev->config_header.intr_line);
1228
1229     return 0;
1230 }
1231
1232 static int init_ide_state(struct vm_device * dev) {
1233     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
1234     int i;
1235
1236     /* 
1237      * Check if the PIIX 3 actually represents both IDE channels in a single PCI entry 
1238      */
1239
1240     for (i = 0; i < 1; i++) {
1241         init_channel(&(ide->channels[i]));
1242
1243         // JRL: this is a terrible hack...
1244         ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
1245     }
1246
1247
1248     return 0;
1249 }
1250
1251
1252
1253 static int init_ide(struct vm_device * dev) {
1254     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
1255
1256     PrintDebug("IDE: Initializing IDE\n");
1257
1258     if (init_ide_state(dev) == -1) {
1259         PrintError("Failed to initialize IDE state\n");
1260         return -1;
1261     }
1262
1263
1264     v3_dev_hook_io(dev, PRI_DATA_PORT, 
1265                    &ide_read_data_port, &write_data_port);
1266     v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
1267                    &read_port_std, &write_port_std);
1268     v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
1269                    &read_port_std, &write_port_std);
1270     v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
1271                    &read_port_std, &write_port_std);
1272     v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
1273                    &read_port_std, &write_port_std);
1274     v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
1275                    &read_port_std, &write_port_std);
1276     v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
1277                    &read_port_std, &write_port_std);
1278     v3_dev_hook_io(dev, PRI_CMD_PORT, 
1279                    &read_port_std, &write_cmd_port);
1280
1281     v3_dev_hook_io(dev, SEC_DATA_PORT, 
1282                    &ide_read_data_port, &write_data_port);
1283     v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
1284                    &read_port_std, &write_port_std);
1285     v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
1286                    &read_port_std, &write_port_std);
1287     v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
1288                    &read_port_std, &write_port_std);
1289     v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
1290                    &read_port_std, &write_port_std);
1291     v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
1292                    &read_port_std, &write_port_std);
1293     v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
1294                    &read_port_std, &write_port_std);
1295     v3_dev_hook_io(dev, SEC_CMD_PORT, 
1296                    &read_port_std, &write_cmd_port);
1297   
1298
1299     v3_dev_hook_io(dev, PRI_CTRL_PORT, 
1300                    &read_port_std, &write_port_std);
1301
1302     v3_dev_hook_io(dev, SEC_CTRL_PORT, 
1303                    &read_port_std, &write_port_std);
1304   
1305
1306     v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
1307                    &read_port_std, &write_port_std);
1308
1309     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
1310                    &read_port_std, &write_port_std);
1311
1312
1313
1314
1315     if (ide->pci_bus) {
1316         struct v3_pci_bar bars[6];
1317         struct v3_southbridge * southbridge = (struct v3_southbridge *)(ide->southbridge);
1318         struct pci_device * sb_pci = (struct pci_device *)(southbridge->southbridge_pci);
1319         struct pci_device * pci_dev = NULL;
1320         int i;
1321
1322         for (i = 0; i < 6; i++) {
1323             bars[i].type = PCI_BAR_NONE;
1324         }
1325
1326         bars[4].type = PCI_BAR_IO;
1327         bars[4].default_base_port = PRI_DEFAULT_DMA_PORT;
1328         bars[4].num_ports = 16;
1329
1330         bars[4].io_read = read_dma_port;
1331         bars[4].io_write = write_dma_port;
1332         
1333         pci_dev = v3_pci_register_device(ide->pci_bus, PCI_STD_DEVICE, 0, sb_pci->dev_num, 1, 
1334                                          "PIIX3_IDE", bars,
1335                                          pci_config_update, NULL, NULL, dev);
1336
1337         if (pci_dev == NULL) {
1338             PrintError("Failed to register IDE BUS %d with PCI\n", i); 
1339             return -1;
1340         }
1341
1342         /* This is for CMD646 devices 
1343            pci_dev->config_header.vendor_id = 0x1095;
1344            pci_dev->config_header.device_id = 0x0646;
1345            pci_dev->config_header.revision = 0x8f07;
1346         */
1347
1348         pci_dev->config_header.vendor_id = 0x8086;
1349         pci_dev->config_header.device_id = 0x7010;
1350         pci_dev->config_header.revision = 0x00;
1351
1352         pci_dev->config_header.prog_if = 0x80;
1353         pci_dev->config_header.subclass = 0x01;
1354         pci_dev->config_header.class = 0x01;
1355
1356         pci_dev->config_header.command = 0;
1357         pci_dev->config_header.status = 0x0280;
1358
1359         ide->ide_pci = pci_dev;
1360
1361
1362     }
1363
1364     return 0;
1365 }
1366
1367
1368 static int deinit_ide(struct vm_device * dev) {
1369     // unhook io ports....
1370     // deregister from PCI?
1371     return 0;
1372 }
1373
1374
1375 static struct vm_device_ops dev_ops = {
1376     .init = init_ide,
1377     .deinit = deinit_ide,
1378     .reset = NULL,
1379     .start = NULL,
1380     .stop = NULL,
1381 };
1382
1383
1384 struct vm_device *  v3_create_ide(struct vm_device * pci_bus, struct vm_device * southbridge_dev) {
1385     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
1386     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
1387
1388     ide->pci_bus = pci_bus;
1389     ide->southbridge = (struct v3_southbridge *)(southbridge_dev->private_data);
1390
1391     PrintDebug("IDE: Creating IDE bus x 2\n");
1392
1393     return device;
1394 }
1395
1396
1397
1398 int v3_ide_get_geometry(struct vm_device * ide_dev, int channel_num, int drive_num, 
1399                         uint32_t * cylinders, uint32_t * heads, uint32_t * sectors) {
1400
1401     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1402     struct ide_channel * channel = &(ide->channels[channel_num]);
1403     struct ide_drive * drive = &(channel->drives[drive_num]);
1404     
1405     if (drive->drive_type == IDE_NONE) {
1406         return -1;
1407     }
1408
1409     *cylinders = drive->num_cylinders;
1410     *heads = drive->num_heads;
1411     *sectors = drive->num_sectors;
1412
1413     return 0;
1414 }
1415
1416
1417
1418
1419 int v3_ide_register_cdrom(struct vm_device * ide_dev, 
1420                           uint_t bus_num, 
1421                           uint_t drive_num,
1422                           char * dev_name, 
1423                           struct v3_ide_cd_ops * ops, 
1424                           void * private_data) {
1425
1426     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1427     struct ide_channel * channel = NULL;
1428     struct ide_drive * drive = NULL;
1429
1430     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1431     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1432
1433     channel = &(ide->channels[bus_num]);
1434     drive = &(channel->drives[drive_num]);
1435     
1436     if (drive->drive_type != IDE_NONE) {
1437         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1438         return -1;
1439     }
1440
1441     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1442
1443     while (strlen((char *)(drive->model)) < 40) {
1444         strcat((char*)(drive->model), " ");
1445     }
1446
1447
1448     drive->drive_type = IDE_CDROM;
1449
1450     drive->cd_ops = ops;
1451
1452     if (ide->ide_pci) {
1453         // Hardcode this for now, but its not a good idea....
1454         ide->ide_pci->config_space[0x41 + (bus_num * 2)] = 0x80;
1455     }
1456
1457     drive->private_data = private_data;
1458
1459     return 0;
1460 }
1461
1462
1463 int v3_ide_register_harddisk(struct vm_device * ide_dev, 
1464                              uint_t bus_num, 
1465                              uint_t drive_num, 
1466                              char * dev_name, 
1467                              struct v3_ide_hd_ops * ops, 
1468                              void * private_data) {
1469
1470     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1471     struct ide_channel * channel = NULL;
1472     struct ide_drive * drive = NULL;
1473
1474     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1475     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1476
1477     channel = &(ide->channels[bus_num]);
1478     drive = &(channel->drives[drive_num]);
1479     
1480     if (drive->drive_type != IDE_NONE) {
1481         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1482         return -1;
1483     }
1484
1485     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1486
1487     drive->drive_type = IDE_DISK;
1488
1489     drive->hd_state.accessed = 0;
1490     drive->hd_state.mult_sector_num = 1;
1491
1492     drive->hd_ops = ops;
1493
1494     /* this is something of a hack... */
1495     drive->num_sectors = 63;
1496     drive->num_heads = 16;
1497     drive->num_cylinders = (ops->get_capacity(private_data) / 512) / (drive->num_sectors * drive->num_heads);
1498
1499     if (ide->ide_pci) {
1500         // Hardcode this for now, but its not a good idea....
1501         ide->ide_pci->config_space[0x41 + (bus_num * 2)] = 0x80;
1502     }
1503
1504
1505
1506     drive->private_data = private_data;
1507
1508     return 0;
1509 }
1510
1511
1512