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.


more updates for DMA
[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 pci_bar_update(struct pci_device * pci_dev, uint_t bar) {
871     PrintError("IDE does not support bar updates\n");
872     return -1;
873 }
874
875
876 static int init_ide_state(struct vm_device * dev) {
877     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
878     struct v3_pci_bar bars[6];
879     struct pci_device * pci_dev = NULL;
880     int i, j;
881
882     for (i = 0; i < 2; i++) {
883         init_channel(&(ide->channels[i]));
884
885         // JRL: this is a terrible hack...
886         ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
887
888         for (j = 0; j < 6; j++) {
889             bars[j].type = PCI_BAR_NONE;
890             bars[j].mem_hook = 0;
891             bars[j].num_pages = 0;
892             bars[j].bar_update = NULL;
893         }
894
895
896         bars[4].type = PCI_BAR_IO;
897         bars[4].bar_update = pci_bar_update;
898
899         pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
900                                          NULL, NULL, NULL, dev);
901
902         if (pci_dev == NULL) {
903             PrintError("Failed to register IDE BUS %d with PCI\n", i); 
904             return -1;
905         }
906
907         ide->channels[i].pci_dev = pci_dev;
908
909         pci_dev->config_header.vendor_id = 0x1095;
910         pci_dev->config_header.device_id = 0x0646;
911         pci_dev->config_header.revision = 0x8f07;
912         pci_dev->config_header.subclass = 0x01;
913         pci_dev->config_header.class = 0x01;
914     }
915
916
917
918     /* Register PIIX3 Busmaster PCI device */
919     for (j = 0; j < 6; j++) {
920         bars[j].type = PCI_BAR_NONE;
921         bars[j].mem_hook = 0;
922         bars[j].num_pages = 0;
923         bars[j].bar_update = NULL;
924     }
925
926     pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "PIIX3 IDE", -1, bars,
927                                      NULL, NULL, NULL, dev);
928     
929     
930     ide->busmaster_pci = pci_dev;
931
932     pci_dev->config_header.vendor_id = 0x8086;
933     pci_dev->config_header.device_id = 0x7010;
934     pci_dev->config_header.revision = 0x80;
935     pci_dev->config_header.subclass = 0x01;
936     pci_dev->config_header.class = 0x01;
937
938
939     return 0;
940 }
941
942
943
944 static int init_ide(struct vm_device * dev) {
945     //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
946
947     PrintDebug("IDE: Initializing IDE\n");
948
949     if (init_ide_state(dev) == -1) {
950         PrintError("Failed to initialize IDE state\n");
951         return -1;
952     }
953
954
955
956
957     v3_dev_hook_io(dev, PRI_DATA_PORT, 
958                    &ide_read_data_port, &write_data_port);
959     v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
960                    &read_port_std, &write_port_std);
961     v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
962                    &read_port_std, &write_port_std);
963     v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
964                    &read_port_std, &write_port_std);
965     v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
966                    &read_port_std, &write_port_std);
967     v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
968                    &read_port_std, &write_port_std);
969     v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
970                    &read_port_std, &write_port_std);
971     v3_dev_hook_io(dev, PRI_CMD_PORT, 
972                    &read_port_std, &write_cmd_port);
973
974     v3_dev_hook_io(dev, SEC_DATA_PORT, 
975                    &ide_read_data_port, &write_data_port);
976     v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
977                    &read_port_std, &write_port_std);
978     v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
979                    &read_port_std, &write_port_std);
980     v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
981                    &read_port_std, &write_port_std);
982     v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
983                    &read_port_std, &write_port_std);
984     v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
985                    &read_port_std, &write_port_std);
986     v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
987                    &read_port_std, &write_port_std);
988     v3_dev_hook_io(dev, SEC_CMD_PORT, 
989                    &read_port_std, &write_cmd_port);
990   
991
992     v3_dev_hook_io(dev, PRI_CTRL_PORT, 
993                    &read_port_std, &write_port_std);
994
995     v3_dev_hook_io(dev, SEC_CTRL_PORT, 
996                    &read_port_std, &write_port_std);
997   
998
999     v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
1000                    &read_port_std, &write_port_std);
1001
1002     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
1003                    &read_port_std, &write_port_std);
1004
1005
1006
1007     v3_dev_hook_io(dev, PRI_DMA_CMD_PORT, 
1008                    &read_dma_port, &write_dma_port);
1009     v3_dev_hook_io(dev, PRI_DMA_STATUS_PORT, 
1010                    &read_dma_port, &write_dma_port);
1011     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1012                    &read_dma_port, &write_dma_port);
1013     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1014                    &read_dma_port, &write_dma_port);
1015     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1016                    &read_dma_port, &write_dma_port);
1017     v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
1018                    &read_dma_port, &write_dma_port);
1019
1020
1021     v3_dev_hook_io(dev, SEC_DMA_CMD_PORT, 
1022                    &read_dma_port, &write_dma_port);
1023     v3_dev_hook_io(dev, SEC_DMA_STATUS_PORT, 
1024                    &read_dma_port, &write_dma_port);
1025     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1026                    &read_dma_port, &write_dma_port);
1027     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1028                    &read_dma_port, &write_dma_port);
1029     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1030                    &read_dma_port, &write_dma_port);
1031     v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
1032                    &read_dma_port, &write_dma_port);
1033
1034     return 0;
1035 }
1036
1037
1038 static int deinit_ide(struct vm_device * dev) {
1039     // unhook io ports....
1040     // deregister from PCI?
1041     return 0;
1042 }
1043
1044
1045 static struct vm_device_ops dev_ops = {
1046     .init = init_ide,
1047     .deinit = deinit_ide,
1048     .reset = NULL,
1049     .start = NULL,
1050     .stop = NULL,
1051 };
1052
1053
1054 struct vm_device *  v3_create_ide(struct vm_device * pci) {
1055     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
1056     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
1057
1058     ide->pci = pci;
1059
1060     PrintDebug("IDE: Creating IDE bus x 2\n");
1061
1062     return device;
1063 }
1064
1065
1066
1067
1068
1069 int v3_ide_register_cdrom(struct vm_device * ide_dev, 
1070                           uint_t bus_num, 
1071                           uint_t drive_num,
1072                           char * dev_name, 
1073                           struct v3_ide_cd_ops * ops, 
1074                           void * private_data) {
1075
1076     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1077     struct ide_channel * channel = NULL;
1078     struct ide_drive * drive = NULL;
1079
1080     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1081     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1082
1083     channel = &(ide->channels[bus_num]);
1084     drive = &(channel->drives[drive_num]);
1085     
1086     if (drive->drive_type != IDE_NONE) {
1087         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1088         return -1;
1089     }
1090
1091     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1092
1093     while (strlen((char *)(drive->model)) < 40) {
1094         strcat((char*)(drive->model), " ");
1095     }
1096
1097
1098     drive->drive_type = IDE_CDROM;
1099
1100     drive->cd_ops = ops;
1101
1102     drive->private_data = private_data;
1103
1104     return 0;
1105 }
1106
1107
1108 int v3_ide_register_harddisk(struct vm_device * ide_dev, 
1109                              uint_t bus_num, 
1110                              uint_t drive_num, 
1111                              char * dev_name, 
1112                              struct v3_ide_hd_ops * ops, 
1113                              void * private_data) {
1114
1115     struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
1116     struct ide_channel * channel = NULL;
1117     struct ide_drive * drive = NULL;
1118
1119     V3_ASSERT((bus_num >= 0) && (bus_num < 2));
1120     V3_ASSERT((drive_num >= 0) && (drive_num < 2));
1121
1122     channel = &(ide->channels[bus_num]);
1123     drive = &(channel->drives[drive_num]);
1124     
1125     if (drive->drive_type != IDE_NONE) {
1126         PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
1127         return -1;
1128     }
1129
1130     strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
1131
1132     drive->drive_type = IDE_DISK;
1133
1134     drive->hd_ops = ops;
1135
1136     drive->private_data = private_data;
1137
1138     return 0;
1139 }