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.


updated PCI
[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 <devices/pci.h>
23 #include "ide-types.h"
24 #include "atapi-types.h"
25
26 #define PRI_DEFAULT_IRQ 14
27 #define SEC_DEFAULT_IRQ 15
28
29
30 #define PRI_DATA_PORT         0x1f0
31 #define PRI_FEATURES_PORT     0x1f1
32 #define PRI_SECT_CNT_PORT     0x1f2
33 #define PRI_SECT_NUM_PORT     0x1f3
34 #define PRI_CYL_LOW_PORT      0x1f4
35 #define PRI_CYL_HIGH_PORT     0x1f5
36 #define PRI_DRV_SEL_PORT      0x1f6
37 #define PRI_CMD_PORT          0x1f7
38 #define PRI_CTRL_PORT         0x3f6
39 #define PRI_ADDR_REG_PORT     0x3f7
40
41 #define SEC_DATA_PORT         0x170
42 #define SEC_FEATURES_PORT     0x171
43 #define SEC_SECT_CNT_PORT     0x172
44 #define SEC_SECT_NUM_PORT     0x173
45 #define SEC_CYL_LOW_PORT      0x174
46 #define SEC_CYL_HIGH_PORT     0x175
47 #define SEC_DRV_SEL_PORT      0x176
48 #define SEC_CMD_PORT          0x177
49 #define SEC_CTRL_PORT         0x376
50 #define SEC_ADDR_REG_PORT     0x377
51
52
53 #define PRI_DMA_CMD_PORT      0xc000
54 #define PRI_DMA_STATUS_PORT   0xc002
55 #define PRI_DMA_PRD_PORT0     0xc004
56 #define PRI_DMA_PRD_PORT1     0xc005
57 #define PRI_DMA_PRD_PORT2     0xc006
58 #define PRI_DMA_PRD_PORT3     0xc007
59
60 #define SEC_DMA_CMD_PORT      0xc008
61 #define SEC_DMA_STATUS_PORT   0xc00a
62 #define SEC_DMA_PRD_PORT0     0xc00c
63 #define SEC_DMA_PRD_PORT1     0xc00d
64 #define SEC_DMA_PRD_PORT2     0xc00e
65 #define SEC_DMA_PRD_PORT3     0xc00f
66
67 #define DATA_BUFFER_SIZE 2048
68
69 static const char * ide_pri_port_strs[] = {"PRI_DATA", "PRI_FEATURES", "PRI_SECT_CNT", "PRI_SECT_NUM", 
70                                           "PRI_CYL_LOW", "PRI_CYL_HIGH", "PRI_DRV_SEL", "PRI_CMD",
71                                            "PRI_CTRL", "PRI_ADDR_REG"};
72
73
74 static const char * ide_sec_port_strs[] = {"SEC_DATA", "SEC_FEATURES", "SEC_SECT_CNT", "SEC_SECT_NUM", 
75                                           "SEC_CYL_LOW", "SEC_CYL_HIGH", "SEC_DRV_SEL", "SEC_CMD",
76                                            "SEC_CTRL", "SEC_ADDR_REG"};
77
78 static const char * ide_dma_port_strs[] = {"PRI_DMA_CMD", NULL,
79                                            "PRI_DMA_STATUS", NULL,
80                                            "PRI_DMA_PRD0", "PRI_DMA_PRD1", 
81                                            "PRI_DMA_PRD2", "PRI_DMA_PRD3",
82                                            "SEC_DMA_CMD", NULL,
83                                            "SEC_DMA_STATUS", NULL,
84                                            "SEC_DMA_PRD0","SEC_DMA_PRD1",
85                                            "SEC_DMA_PRD2","SEC_DMA_PRD3"};
86
87
88
89 static inline const char * io_port_to_str(uint16_t port) {
90     if ((port >= PRI_DATA_PORT) && (port <= PRI_CMD_PORT)) {
91         return ide_pri_port_strs[port - PRI_DATA_PORT];
92     } else if ((port >= SEC_DATA_PORT) && (port <= SEC_CMD_PORT)) {
93         return ide_sec_port_strs[port - SEC_DATA_PORT];
94     } else if ((port == PRI_CTRL_PORT) || (port == PRI_ADDR_REG_PORT)) {
95         return ide_pri_port_strs[port - PRI_CTRL_PORT + 8];
96     } else if ((port == SEC_CTRL_PORT) || (port == SEC_ADDR_REG_PORT)) {
97         return ide_sec_port_strs[port - SEC_CTRL_PORT + 8];
98     } else if ((port >= PRI_DMA_CMD_PORT) && (port <= SEC_DMA_PRD_PORT3)) {
99         return ide_dma_port_strs[port - PRI_DMA_CMD_PORT];
100     } 
101     return NULL;
102 }
103
104
105
106 static const char * ide_dev_type_strs[] = {"HARDDISK", "CDROM", "NONE"};
107
108
109 static inline const char * device_type_to_str(v3_ide_dev_type_t type) {
110     if (type > 2) {
111         return NULL;
112     }
113
114     return ide_dev_type_strs[type];
115 }
116
117
118
119 struct ide_cd_state {
120     struct atapi_sense_data sense;
121     uint_t current_lba;
122     uint8_t atapi_cmd;
123     struct atapi_error_recovery err_recovery;
124 };
125
126 struct ide_hd_state {
127
128 };
129
130 struct ide_drive {
131     // Command Registers
132
133     v3_ide_dev_type_t drive_type;
134
135     union {
136         struct v3_ide_cd_ops * cd_ops;
137         struct v3_ide_hd_ops * hd_ops;
138     };
139
140
141     union {
142         struct ide_cd_state cd_state;
143         struct ide_hd_state hd_state;
144     };
145
146     char model[41];
147
148     // Where we are in the data transfer
149     uint_t transfer_index;
150
151     // the length of a transfer
152     // calculated for easy access
153     uint_t transfer_length;
154
155
156     // We have a local data buffer that we use for IO port accesses
157     uint8_t data_buf[DATA_BUFFER_SIZE];
158
159
160     void * private_data;
161     
162     union {
163         uint8_t sector_count;             // 0x1f2,0x172
164         struct atapi_irq_flags irq_flags;
165     } __attribute__((packed));
166
167     union {
168         uint8_t sector_num;               // 0x1f3,0x173
169         uint8_t lba0;
170     };
171
172     union {
173         uint16_t cylinder;
174         uint16_t lba12;
175
176
177         struct {
178             uint8_t cylinder_low;       // 0x1f4,0x174
179             uint8_t cylinder_high;      // 0x1f5,0x175
180         } __attribute__((packed));
181
182         struct {
183             uint8_t lba1;
184             uint8_t lba2;
185         } __attribute__((packed));
186
187
188         // The transfer length requested by the CPU 
189         uint16_t req_len;
190     } __attribute__((packed));
191
192     struct ide_dma_cmd_reg dma_cmd;
193     struct ide_dma_status_reg dma_status;
194     uint32_t dma_prd_addr;
195
196 };
197
198
199
200 struct ide_channel {
201     struct ide_drive drives[2];
202
203     // Command Registers
204     struct ide_error_reg error_reg;     // [read] 0x1f1,0x171
205
206     struct ide_features_reg features;
207
208     struct ide_drive_head_reg drive_head; // 0x1f6,0x176
209
210     struct ide_status_reg status;       // [read] 0x1f7,0x177
211     uint8_t cmd_reg;                // [write] 0x1f7,0x177
212
213     int irq; // this is temporary until we add PCI support
214
215     struct pci_device * pci_dev;
216
217     // Control Registers
218     struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
219 };
220
221
222
223 struct ide_internal {
224     struct ide_channel channels[2];
225     struct vm_device * pci;
226     struct pci_device * busmaster_pci;
227 };
228
229
230
231 static inline uint16_t be_to_le_16(const uint16_t val) {
232     uint8_t * buf = (uint8_t *)&val;
233     return (buf[0] << 8) | (buf[1]) ;
234 }
235
236 static inline uint16_t le_to_be_16(const uint16_t val) {
237     return be_to_le_16(val);
238 }
239
240
241 static inline uint32_t be_to_le_32(const uint32_t val) {
242     uint8_t * buf = (uint8_t *)&val;
243     return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
244 }
245
246 static inline uint32_t le_to_be_32(const uint32_t val) {
247     return be_to_le_32(val);
248 }
249
250
251 static inline int get_channel_index(ushort_t port) {
252     if (((port & 0xfff8) == 0x1f0) ||
253         ((port & 0xfffe) == 0x3f6) || 
254         ((port & 0xfff8) == 0xc000)) {
255         return 0;
256     } else if (((port & 0xfff8) == 0x170) ||
257                ((port & 0xfffe) == 0x376) ||
258                ((port & 0xfff8) == 0xc008)) {
259         return 1;
260     }
261
262     return -1;
263 }
264
265 static inline struct ide_channel * get_selected_channel(struct ide_internal * ide, ushort_t port) {
266     int channel_idx = get_channel_index(port);    
267     return &(ide->channels[channel_idx]);
268 }
269
270 static inline struct ide_drive * get_selected_drive(struct ide_channel * channel) {
271     return &(channel->drives[channel->drive_head.drive_sel]);
272 }
273
274
275 static inline int is_lba_enabled(struct ide_channel * channel) {
276     return channel->drive_head.lba_mode;
277 }
278
279
280 static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
281     if (channel->ctrl_reg.irq_disable == 0) {
282         v3_raise_irq(dev->vm, channel->irq);
283     }
284 }
285
286
287 static void drive_reset(struct ide_drive * drive) {
288     drive->sector_count = 0x01;
289     drive->sector_num = 0x01;
290     
291     if (drive->drive_type == IDE_CDROM) {
292         drive->cylinder = 0xeb14;
293     } else {
294         drive->cylinder = 0x0000;
295     }
296
297
298     memset(drive->data_buf, 0, sizeof(drive->data_buf));
299     drive->transfer_index = 0;
300
301     // Send the reset signal to the connected device callbacks
302     //     channel->drives[0].reset();
303     //    channel->drives[1].reset();
304 }
305
306 static void channel_reset(struct ide_channel * channel) {
307     
308     // set busy and seek complete flags
309     channel->status.val = 0x90;
310
311     // Clear errors
312     channel->error_reg.val = 0x01;
313
314     // clear commands
315     channel->cmd_reg = 0x00;
316
317     channel->ctrl_reg.irq_disable = 0;
318 }
319
320 static void channel_reset_complete(struct ide_channel * channel) {
321     channel->status.busy = 0;
322     channel->status.ready = 1;
323
324     channel->drive_head.head_num = 0;    
325     
326     drive_reset(&(channel->drives[0]));
327     drive_reset(&(channel->drives[1]));
328 }
329
330
331 static void ide_abort_command(struct vm_device * dev, struct ide_channel * channel) {
332     channel->status.val = 0x41; // Error + ready
333     channel->error_reg.val = 0x04; // No idea...
334
335     ide_raise_irq(dev, channel);
336 }
337
338
339 // Include the ATAPI interface handlers
340 #include "atapi.h"
341
342
343 static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
344     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
345     struct ide_channel * channel = get_selected_channel(ide, port);
346     struct ide_drive * drive = get_selected_drive(channel);
347
348     if (length != 1) {
349         PrintError("IDE: Invalid Write length on IDE port %x\n", port);
350         return -1;
351     }
352
353     PrintDebug("IDE: Writing DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
354
355     switch (port) {
356         case PRI_DMA_CMD_PORT:
357         case SEC_DMA_CMD_PORT:
358             drive->dma_cmd.val = *(uint8_t *)src;
359             break;
360
361         case PRI_DMA_STATUS_PORT:
362         case SEC_DMA_STATUS_PORT:
363             drive->dma_status.val = *(uint8_t *)src;
364             break;
365
366         case PRI_DMA_PRD_PORT0:
367         case PRI_DMA_PRD_PORT1:
368         case PRI_DMA_PRD_PORT2:
369         case PRI_DMA_PRD_PORT3:
370         case SEC_DMA_PRD_PORT0:
371         case SEC_DMA_PRD_PORT1:
372         case SEC_DMA_PRD_PORT2:
373         case SEC_DMA_PRD_PORT3: {
374             uint_t addr_index = port & 0x3;
375             uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
376
377             addr_buf[addr_index] = *(uint8_t *)src;
378             break;
379         }
380         default:
381             PrintError("IDE: Invalid DMA Port (%x)\n", port);
382             return -1;
383     }
384
385     return length;
386 }
387
388
389 static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
390     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
391     struct ide_channel * channel = get_selected_channel(ide, port);
392     struct ide_drive * drive = get_selected_drive(channel);
393
394     if (length != 1) {
395         PrintError("IDE: Invalid Write length on IDE port %x\n", port);
396         return -1;
397     }
398
399
400
401     switch (port) {
402         case PRI_DMA_CMD_PORT:
403         case SEC_DMA_CMD_PORT:
404             *(uint8_t *)dst = drive->dma_cmd.val;
405             break;
406
407         case PRI_DMA_STATUS_PORT:
408         case SEC_DMA_STATUS_PORT:
409             *(uint8_t *)dst = drive->dma_status.val;
410             break;
411
412         case PRI_DMA_PRD_PORT0:
413         case PRI_DMA_PRD_PORT1:
414         case PRI_DMA_PRD_PORT2:
415         case PRI_DMA_PRD_PORT3:
416         case SEC_DMA_PRD_PORT0:
417         case SEC_DMA_PRD_PORT1:
418         case SEC_DMA_PRD_PORT2:
419         case SEC_DMA_PRD_PORT3: {
420             uint_t addr_index = port & 0x3;
421             uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
422
423             *(uint8_t *)dst = addr_buf[addr_index];
424             break;
425         }
426         default:
427             PrintError("IDE: Invalid DMA Port (%x)\n", port);
428             return -1;
429     }
430
431     PrintDebug("IDE: Reading DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)dst);
432
433     return length;
434 }
435
436
437
438 static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
439     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
440     struct ide_channel * channel = get_selected_channel(ide, port);
441     struct ide_drive * drive = get_selected_drive(channel);
442
443     if (length != 1) {
444         PrintError("Invalid Write Length on IDE command Port %x\n", port);
445         return -1;
446     }
447
448     PrintDebug("IDE: Writing Command Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
449     
450     channel->cmd_reg = *(uint8_t *)src;
451     
452     switch (channel->cmd_reg) {
453         
454         case 0xa0: // ATAPI Command Packet
455             if (drive->drive_type != IDE_CDROM) {
456                 ide_abort_command(dev, channel);
457             }
458             
459             drive->sector_count = 1;
460
461             channel->status.busy = 0;
462             channel->status.write_fault = 0;
463             channel->status.data_req = 1;
464             channel->status.error = 0;
465
466             // reset the data buffer...
467             drive->transfer_length = ATAPI_PACKET_SIZE;
468             drive->transfer_index = 0;
469
470             break;
471         case 0xa1: // ATAPI Identify Device Packet
472             atapi_identify_device(drive);
473
474             channel->error_reg.val = 0;
475             channel->status.val = 0x58; // ready, data_req, seek_complete
476             
477             ide_raise_irq(dev, channel);
478             break;
479         case 0xec: // Identify Device
480             if (drive->drive_type != IDE_DISK) {
481                 drive_reset(drive);
482
483                 // JRL: Should we abort here?
484                 ide_abort_command(dev, channel);
485             } else {
486                 PrintError("IDE Disks currently not implemented\n");
487                 return -1;
488             }
489             break;
490         default:
491             PrintError("Unimplemented IDE command (%x)\n", channel->cmd_reg);
492             return -1;
493     }
494
495     return length;
496 }
497
498
499 static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
500     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
501     struct ide_channel * channel = get_selected_channel(ide, port);
502     struct ide_drive * drive = get_selected_drive(channel);
503
504     //    PrintDebug("IDE: Writing Data Port %x (val=%x, len=%d)\n", 
505     //         port, *(uint32_t *)src, length);
506     
507     memcpy(drive->data_buf + drive->transfer_index, src, length);    
508     drive->transfer_index += length;
509
510     // Transfer is complete, dispatch the command
511     if (drive->transfer_index >= drive->transfer_length) {
512         switch (channel->cmd_reg) {
513             case 0x30: // Write Sectors
514                 PrintError("Writing Data not yet implemented\n");
515                 return -1;
516                 
517             case 0xa0: // ATAPI packet command
518                 if (atapi_handle_packet(dev, channel) == -1) {
519                     PrintError("Error handling ATAPI packet\n");
520                     return -1;
521                 }
522                 break;
523             default:
524                 PrintError("Unhandld IDE Command %x\n", channel->cmd_reg);
525                 return -1;
526         }
527     }
528
529     return length;
530 }
531
532
533 static int read_hd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
534     PrintError("Harddrive data port read not implemented\n");
535     return -1;
536 }
537
538
539
540 static int read_cd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
541     struct ide_drive * drive = get_selected_drive(channel);
542     int data_offset = drive->transfer_index % DATA_BUFFER_SIZE;
543     int req_offset = drive->transfer_index % drive->req_len;
544     
545     if (drive->cd_state.atapi_cmd != 0x28) {
546         PrintDebug("IDE: Reading CD Data (len=%d) (req_len=%d)\n", length, drive->req_len);
547     }
548
549     if (drive->transfer_index >= drive->transfer_length) {
550         PrintError("Buffer Overrun... (xfer_len=%d) (cur_idx=%d) (post_idx=%d)\n", 
551                    drive->transfer_length, drive->transfer_index, 
552                    drive->transfer_index + length);
553         return -1;
554     }
555
556
557
558     if ((data_offset == 0) && (drive->transfer_index > 0)) {
559         
560         if (drive->drive_type == IDE_CDROM) {
561             if (atapi_update_data_buf(dev, channel) == -1) {
562                 PrintError("Could not update CDROM data buffer\n");
563                 return -1;
564             } 
565         } else {
566             PrintError("IDE Harddrives not implemented\n");
567             return -1;
568         }
569     }
570
571     memcpy(dst, drive->data_buf + data_offset, length);
572     
573     drive->transfer_index += length;
574
575     if ((req_offset == 0) && (drive->transfer_index > 0)) {
576         if (drive->transfer_index < drive->transfer_length) {
577             // An increment is complete, but there is still more data to be transferred...
578             
579             channel->status.data_req = 1;
580
581             drive->irq_flags.c_d = 0;
582
583             // Update the request length in the cylinder regs
584             if (atapi_update_req_len(dev, channel, drive->transfer_length - drive->transfer_index) == -1) {
585                 PrintError("Could not update request length after completed increment\n");
586                 return -1;
587             }
588         } else {
589             // This was the final read of the request
590             channel->status.data_req = 0;
591             channel->status.ready = 1;
592             
593             drive->irq_flags.c_d = 1;
594             drive->irq_flags.rel = 0;
595         }
596
597         drive->irq_flags.io_dir = 1;
598         channel->status.busy = 0;
599
600         ide_raise_irq(dev, channel);
601     }
602
603     return length;
604 }
605
606
607 static int read_drive_id(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
608     struct ide_drive * drive = get_selected_drive(channel);
609
610     channel->status.busy = 0;
611     channel->status.ready = 1;
612     channel->status.write_fault = 0;
613     channel->status.seek_complete = 1;
614     channel->status.corrected = 0;
615     channel->status.error = 0;
616                 
617     
618     memcpy(dst, drive->data_buf + drive->transfer_index, length);
619     drive->transfer_index += length;
620     
621     if (drive->transfer_index >= drive->transfer_length) {
622         channel->status.data_req = 0;
623     }
624     
625     return length;
626 }
627
628
629 static int ide_read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
630     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
631     struct ide_channel * channel = get_selected_channel(ide, port);
632     struct ide_drive * drive = get_selected_drive(channel);
633
634     //    PrintDebug("IDE: Reading Data Port %x (len=%d)\n", port, length);
635
636     if ((channel->cmd_reg == 0xec) ||
637         (channel->cmd_reg == 0xa1)) {
638         return read_drive_id((uint8_t *)dst, length, dev, channel);
639     }
640
641     if (drive->drive_type == IDE_CDROM) {
642         if (read_cd_data((uint8_t *)dst, length, dev, channel) == -1) {
643             PrintError("IDE: Could not read CD Data\n");
644             return -1;
645         }
646     } else if (drive->drive_type == IDE_DISK) {
647         if (read_hd_data((uint8_t *)dst, length, dev, channel) == -1) {
648             PrintError("IDE: Could not read HD Data\n");
649             return -1;
650         }
651     } else {
652         memset((uint8_t *)dst, 0, length);
653     }
654
655     return length;
656 }
657
658 static int write_port_std(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
659     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
660     struct ide_channel * channel = get_selected_channel(ide, port);
661     struct ide_drive * drive = get_selected_drive(channel);
662             
663     if (length != 1) {
664         PrintError("Invalid Write length on IDE port %x\n", port);
665         return -1;
666     }
667
668     PrintDebug("IDE: Writing Standard Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
669
670
671     switch (port) {
672         // reset and interrupt enable
673         case PRI_CTRL_PORT:
674         case SEC_CTRL_PORT: {
675             struct ide_ctrl_reg * tmp_ctrl = (struct ide_ctrl_reg *)src;
676
677             // only reset channel on a 0->1 reset bit transition
678             if ((!channel->ctrl_reg.soft_reset) && (tmp_ctrl->soft_reset)) {
679                 channel_reset(channel);
680             } else if ((channel->ctrl_reg.soft_reset) && (!tmp_ctrl->soft_reset)) {
681                 channel_reset_complete(channel);
682             }
683
684             channel->ctrl_reg.val = tmp_ctrl->val;          
685             break;
686         }
687         case PRI_FEATURES_PORT:
688         case SEC_FEATURES_PORT:
689             channel->features.val = *(uint8_t *)src;
690             break;
691
692         case PRI_SECT_CNT_PORT:
693         case SEC_SECT_CNT_PORT:
694             drive->sector_count = *(uint8_t *)src;
695             break;
696
697         case PRI_SECT_NUM_PORT:
698         case SEC_SECT_NUM_PORT:
699             drive->sector_num = *(uint8_t *)src;
700
701         case PRI_CYL_LOW_PORT:
702         case SEC_CYL_LOW_PORT:
703             drive->cylinder_low = *(uint8_t *)src;
704             break;
705
706         case PRI_CYL_HIGH_PORT:
707         case SEC_CYL_HIGH_PORT:
708             drive->cylinder_high = *(uint8_t *)src;
709             break;
710
711         case PRI_DRV_SEL_PORT:
712         case SEC_DRV_SEL_PORT: {
713             channel->drive_head.val = *(uint8_t *)src;
714             
715             // make sure the reserved bits are ok..
716             // JRL TODO: check with new ramdisk to make sure this is right...
717             channel->drive_head.val |= 0xa0;
718
719             drive = get_selected_drive(channel);
720
721             // Selecting a non-present device is a no-no
722             if (drive->drive_type == IDE_NONE) {
723                 PrintDebug("Attempting to select a non-present drive\n");
724                 channel->error_reg.abort = 1;
725                 channel->status.error = 1;
726             }
727
728             break;
729         }
730         default:
731             PrintError("IDE: Write to unknown Port %x\n", port);
732             return -1;
733     }
734     return length;
735 }
736
737
738 static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
739     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
740     struct ide_channel * channel = get_selected_channel(ide, port);
741     struct ide_drive * drive = get_selected_drive(channel);
742     
743     if (length != 1) {
744         PrintError("Invalid Read length on IDE port %x\n", port);
745         return -1;
746     }
747
748     PrintDebug("IDE: Reading Standard Port %x (%s)\n", port, io_port_to_str(port));
749
750
751     if ((port == PRI_ADDR_REG_PORT) ||
752         (port == SEC_ADDR_REG_PORT)) {
753         // unused, return 0xff
754         *(uint8_t *)dst = 0xff;
755         return length;
756     }
757
758
759     // if no drive is present just return 0 + reserved bits
760     if (drive->drive_type == IDE_NONE) {
761         if ((port == PRI_DRV_SEL_PORT) ||
762             (port == SEC_DRV_SEL_PORT)) {
763             *(uint8_t *)dst = 0xa0;
764         } else {
765             *(uint8_t *)dst = 0;
766         }
767
768         return length;
769     }
770
771     switch (port) {
772
773         // This is really the error register.
774         case PRI_FEATURES_PORT:
775         case SEC_FEATURES_PORT:
776             *(uint8_t *)dst = channel->error_reg.val;
777             break;
778             
779         case PRI_SECT_CNT_PORT:
780         case SEC_SECT_CNT_PORT:
781             *(uint8_t *)dst = drive->sector_count;
782             break;
783
784         case PRI_SECT_NUM_PORT:
785         case SEC_SECT_NUM_PORT:
786             *(uint8_t *)dst = drive->sector_num;
787             break;
788
789         case PRI_CYL_LOW_PORT:
790         case SEC_CYL_LOW_PORT:
791             *(uint8_t *)dst = drive->cylinder_low;
792             break;
793
794
795         case PRI_CYL_HIGH_PORT:
796         case SEC_CYL_HIGH_PORT:
797             *(uint8_t *)dst = drive->cylinder_high;
798             break;
799
800         case PRI_DRV_SEL_PORT:
801         case SEC_DRV_SEL_PORT:  // hard disk drive and head register 0x1f6
802             *(uint8_t *)dst = channel->drive_head.val;
803             break;
804
805         case PRI_CTRL_PORT:
806         case SEC_CTRL_PORT:
807         case PRI_CMD_PORT:
808         case SEC_CMD_PORT:
809             // Something about lowering interrupts here....
810             *(uint8_t *)dst = channel->status.val;
811             break;
812
813         default:
814             PrintError("Invalid Port: %x\n", port);
815             return -1;
816     }
817
818     PrintDebug("\tVal=%x\n", *(uint8_t *)dst);
819
820     return length;
821 }
822
823
824
825 static void init_drive(struct ide_drive * drive) {
826
827     drive->sector_count = 0x01;
828     drive->sector_num = 0x01;
829     drive->cylinder = 0x0000;
830
831     drive->drive_type = IDE_NONE;
832
833     memset(drive->model, 0, sizeof(drive->model));
834
835     drive->transfer_index = 0;
836     drive->transfer_length = 0;
837     memset(drive->data_buf, 0, sizeof(drive->data_buf));
838
839     drive->dma_cmd.val = 0;
840     drive->dma_status.val = 0;
841     drive->dma_prd_addr = 0;
842
843     drive->private_data = NULL;
844     drive->cd_ops = NULL;
845 }
846
847 static void init_channel(struct ide_channel * channel) {
848     int i = 0;
849
850     channel->error_reg.val = 0x01;
851     channel->drive_head.val = 0x00;
852     channel->status.val = 0x00;
853     channel->cmd_reg = 0x00;
854     channel->ctrl_reg.val = 0x08;
855
856
857     for (i = 0; i < 2; i++) {
858         init_drive(&(channel->drives[i]));
859     }
860
861 }
862
863 /*
864 static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) {
865     PrintError("IDE does not handle PCI config updates\n");
866     return -1;
867 }
868 */
869
870 static int init_ide_state(struct vm_device * dev) {
871     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
872     struct v3_pci_bar bars[6];
873     struct pci_device * pci_dev = NULL;
874     int i, j;
875
876     for (i = 0; i < 2; i++) {
877         init_channel(&(ide->channels[i]));
878
879         // JRL: this is a terrible hack...
880         ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
881
882         for (j = 0; j < 6; j++) {
883             bars[j].type = PCI_BAR_NONE;
884         }
885
886
887         bars[4].type = PCI_BAR_IO;
888         bars[4].default_base_port = PRI_DMA_CMD_PORT + (i * 0x8);
889         bars[4].num_ports = 8;
890         bars[4].io_read = read_dma_port;
891         bars[4].io_write = write_dma_port;
892
893         pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
894                                          NULL, NULL, NULL, dev);
895
896         if (pci_dev == NULL) {
897             PrintError("Failed to register IDE BUS %d with PCI\n", i); 
898             return -1;
899         }
900
901         ide->channels[i].pci_dev = pci_dev;
902
903         pci_dev->config_header.vendor_id = 0x1095;
904         pci_dev->config_header.device_id = 0x0646;
905         pci_dev->config_header.revision = 0x8f07;
906         pci_dev->config_header.subclass = 0x01;
907         pci_dev->config_header.class = 0x01;
908     }
909
910
911
912     /* Register PIIX3 Busmaster PCI device */
913     for (j = 0; j < 6; j++) {
914         bars[j].type = PCI_BAR_NONE;
915     }
916
917     pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "PIIX3 IDE", -1, bars,
918                                      NULL, NULL, NULL, dev);
919     
920     
921     ide->busmaster_pci = pci_dev;
922
923     pci_dev->config_header.vendor_id = 0x8086;
924     pci_dev->config_header.device_id = 0x7010;
925     pci_dev->config_header.revision = 0x80;
926     pci_dev->config_header.subclass = 0x01;
927     pci_dev->config_header.class = 0x01;
928
929
930     return 0;
931 }
932
933
934
935 static int init_ide(struct vm_device * dev) {
936     //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
937
938     PrintDebug("IDE: Initializing IDE\n");
939
940     if (init_ide_state(dev) == -1) {
941         PrintError("Failed to initialize IDE state\n");
942         return -1;
943     }
944
945
946
947
948     v3_dev_hook_io(dev, PRI_DATA_PORT, 
949                    &ide_read_data_port, &write_data_port);
950     v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
951                    &read_port_std, &write_port_std);
952     v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
953                    &read_port_std, &write_port_std);
954     v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
955                    &read_port_std, &write_port_std);
956     v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
957                    &read_port_std, &write_port_std);
958     v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
959                    &read_port_std, &write_port_std);
960     v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
961                    &read_port_std, &write_port_std);
962     v3_dev_hook_io(dev, PRI_CMD_PORT, 
963                    &read_port_std, &write_cmd_port);
964
965     v3_dev_hook_io(dev, SEC_DATA_PORT, 
966                    &ide_read_data_port, &write_data_port);
967     v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
968                    &read_port_std, &write_port_std);
969     v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
970                    &read_port_std, &write_port_std);
971     v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
972                    &read_port_std, &write_port_std);
973     v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
974                    &read_port_std, &write_port_std);
975     v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
976                    &read_port_std, &write_port_std);
977     v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
978                    &read_port_std, &write_port_std);
979     v3_dev_hook_io(dev, SEC_CMD_PORT, 
980                    &read_port_std, &write_cmd_port);
981   
982
983     v3_dev_hook_io(dev, PRI_CTRL_PORT, 
984                    &read_port_std, &write_port_std);
985
986     v3_dev_hook_io(dev, SEC_CTRL_PORT, 
987                    &read_port_std, &write_port_std);
988   
989
990     v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
991                    &read_port_std, &write_port_std);
992
993     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
994                    &read_port_std, &write_port_std);
995
996
997     /*
998
999     v3_dev_hook_io(dev, PRI_DMA_CMD_PORT, 
1000                    &read_dma_port, &write_dma_port);
1001     v3_dev_hook_io(dev, PRI_DMA_STATUS_PORT, 
1002                    &read_dma_port, &write_dma_port);
1003     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1004                    &read_dma_port, &write_dma_port);
1005     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1006                    &read_dma_port, &write_dma_port);
1007     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1008                    &read_dma_port, &write_dma_port);
1009     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1010                    &read_dma_port, &write_dma_port);
1011
1012
1013     v3_dev_hook_io(dev, SEC_DMA_CMD_PORT, 
1014                    &read_dma_port, &write_dma_port);
1015     v3_dev_hook_io(dev, SEC_DMA_STATUS_PORT, 
1016                    &read_dma_port, &write_dma_port);
1017     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1018                    &read_dma_port, &write_dma_port);
1019     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1020                    &read_dma_port, &write_dma_port);
1021     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1022                    &read_dma_port, &write_dma_port);
1023     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1024                    &read_dma_port, &write_dma_port);
1025     */
1026     return 0;
1027 }
1028
1029
1030 static int deinit_ide(struct vm_device * dev) {
1031     // unhook io ports....
1032     // deregister from PCI?
1033     return 0;
1034 }
1035
1036
1037 static struct vm_device_ops dev_ops = {
1038     .init = init_ide,
1039     .deinit = deinit_ide,
1040     .reset = NULL,
1041     .start = NULL,
1042     .stop = NULL,
1043 };
1044
1045
1046 struct vm_device *  v3_create_ide(struct vm_device * pci) {
1047     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
1048     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
1049
1050     ide->pci = pci;
1051
1052     PrintDebug("IDE: Creating IDE bus x 2\n");
1053
1054     return device;
1055 }
1056
1057
1058
1059
1060
1061 int v3_ide_register_cdrom(struct vm_device * ide_dev, 
1062                           uint_t bus_num, 
1063                           uint_t drive_num,
1064                           char * dev_name, 
1065                           struct v3_ide_cd_ops * ops, 
1066                           void * private_data) {
1067
1068     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1069     struct ide_channel * channel = NULL;
1070     struct ide_drive * drive = NULL;
1071
1072     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1073     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1074
1075     channel = &(ide->channels[bus_num]);
1076     drive = &(channel->drives[drive_num]);
1077     
1078     if (drive->drive_type != IDE_NONE) {
1079         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1080         return -1;
1081     }
1082
1083     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1084
1085     while (strlen((char *)(drive->model)) < 40) {
1086         strcat((char*)(drive->model), " ");
1087     }
1088
1089
1090     drive->drive_type = IDE_CDROM;
1091
1092     drive->cd_ops = ops;
1093
1094     drive->private_data = private_data;
1095
1096     return 0;
1097 }
1098
1099
1100 int v3_ide_register_harddisk(struct vm_device * ide_dev, 
1101                              uint_t bus_num, 
1102                              uint_t drive_num, 
1103                              char * dev_name, 
1104                              struct v3_ide_hd_ops * ops, 
1105                              void * private_data) {
1106
1107     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1108     struct ide_channel * channel = NULL;
1109     struct ide_drive * drive = NULL;
1110
1111     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1112     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1113
1114     channel = &(ide->channels[bus_num]);
1115     drive = &(channel->drives[drive_num]);
1116     
1117     if (drive->drive_type != IDE_NONE) {
1118         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1119         return -1;
1120     }
1121
1122     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1123
1124     drive->drive_type = IDE_DISK;
1125
1126     drive->hd_ops = ops;
1127
1128     drive->private_data = private_data;
1129
1130     return 0;
1131 }