} __attribute__((packed));
+
struct ide_drive_head_reg {
union {
uint8_t val;
} __attribute__((packed));
} __attribute__((packed));
+
+
struct ide_status_reg {
union {
uint8_t val;
struct ide_features_reg {
union {
uint8_t val;
+ uint8_t dma; // 1 == DMA, 0 = PIO
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct ide_dma_cmd_reg {
+ union {
+ uint8_t val;
+ struct {
+ uint8_t start : 1;
+ uint8_t rsvd1 : 2;
+ uint8_t read : 1;
+ uint8_t rsvd2 : 4;
+ } __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
+
+struct ide_dma_status_reg {
+ union {
+ uint8_t val;
+ struct {
+ uint8_t active : 1;
+ uint8_t err : 1;
+ uint8_t int_gen : 1;
+ uint8_t rsvd1 : 4;
+ uint8_t prd_int_status : 1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+struct ide_dma_prd {
+ uint32_t base_addr;
+ uint16_t size;
+ uint16_t rsvd : 15;
+ uint8_t end_of_table : 1;
+} __attribute__((packed));
+
+
+
typedef enum {IDE_CTRL_NOT_SPECIFIED,
IDE_CTRL_SINGLE_PORT,
IDE_CTRL_DUAL_PORT,
IDE_CTRL_DUAL_PORT_CACHE} ide_controller_type;
-
struct ide_drive_id {
union {
uint16_t buf[256];
struct {
+ // 0
uint_t rsvd1 : 1;
uint_t hard_sectors : 1;
uint_t no_soft_sectors : 1;
uint_t fmt_speed_tol : 1;
uint_t cdrom_flag : 1;
+ // 1
uint16_t num_cylinders;
+
+ // 2
uint16_t rsvd2;
+
+ // 3
uint16_t num_heads;
-
+ // 4
uint16_t bytes_per_track;
+ // 5
uint16_t bytes_per_sector;
+ // 6
uint16_t sectors_per_track;
+ // 7
uint16_t sector_gap;
+ // 8
uint8_t phase_lock_bytes;
uint8_t rsvd3;
+ // 9
uint16_t num_vendor_wds;
+ // 10
uint8_t serial_num[20]; // right aligned, padded with 0x20
-
+ // 20
uint16_t controller_type;
+ // 21
uint16_t buffer_size; // in 512 byte chunks
-
+
+ // 22
uint16_t num_ecc_bytes;
+ // 23
uint8_t firmware_rev[8]; // space padded
+
+ // 27
uint8_t model_num[40]; // space padded
+ // 47
uint16_t rw_multiples;
+ // 48
uint16_t dword_io;
+ // 49
uint8_t rsvd4;
- uint8_t lba_enable;
-
+ uint8_t dma_enable : 1;
+ uint8_t lba_enable : 1;
+ uint8_t IORDYsw : 1;
+ uint8_t IORDYsup : 1;
+ uint8_t rsvd5 : 4;
+
+ // 50
uint16_t rsvd6;
-
- uint16_t min_PIO_cycle;
- uint16_t min_DMA_cycle;
-
- uint16_t rsvd7[503];
+
+ // 51
+ uint16_t min_PIO_cycle; // 0=slow, 1=medium, 2=fast
+ // 52
+ uint16_t min_DMA_cycle; // 0=slow, 1=medium, 2=fast
+
+ // 53
+ uint16_t field_valid; // 2: ultra_ok word 88
+ // 1: eide_ok words 64-70
+ // 0: cur_ok words 54-58
+ // 54
+ uint16_t cur_cyls;
+ // 55
+ uint16_t cur_heads;
+ // 56
+ uint16_t cur_sectors;
+ // 57
+ uint16_t cur_capacity0;
+ // 58
+ uint16_t cur_capacity1;
+
+ // 59
+ uint8_t cur_mult_sect_cnt;
+ uint8_t mult_sect_valid; // bit0==0: valid
+
+ // 60
+ uint32_t lba_capacity;
+
+ // 62
+ uint16_t dma_lword;
+ // 63
+ uint16_t dma_mword;
+
+ // 64
+ uint16_t eide_pio_modes; // 0: (mode 3), 1: (mode 4)
+ // 65
+ uint16_t eide_dma_min; /* min mword dma cycle time (ns) */
+ // 66
+ uint16_t eide_dma_time; /* recommended mword dma cycle time (ns) */
+ // 67
+ uint16_t eide_pio; /* min cycle time (ns), no IORDY */
+ // 68
+ uint16_t eide_pio_iordy; /* min cycle time (ns), with IORDY */
+
+ // 69
+ uint16_t rsvd7[6];
+
+ // 75
+ uint16_t queue_depth;
+
+ // 76
+ uint16_t rsvd8[4];
+
+ // 80
+ uint16_t major_rev_num;
+ // 81
+ uint16_t minor_rev_num;
+ // 82
+ uint16_t cmd_set_1; /* 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: S
+ */
+
+ // 83
+ uint16_t cmd_set_2; /* 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+
+ // 84
+ uint16_t cfsse; /* cmd set-feature supported extensions
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:6 reserved
+ * 5: General Purpose Logging
+ * 4: Streaming Feature Set
+ * 3: Media Card Pass Through
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+
+ // 85
+ uint16_t cfs_enable_1; /* command set-feature enabled
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ // 86
+ uint16_t cfs_enable_2; /* command set-feature enabled
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ // 87
+ uint16_t csf_default; /* command set-feature default
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:6 reserved
+ * 5: General Purpose Logging enabled
+ * 4: Valid CONFIGURE STREAM executed
+ * 3: Media Card Pass Through enabled
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ // 88
+ uint16_t dma_ultra;
+ // 89
+ uint16_t trs_euc; /* time required for security erase */
+ // 90
+ uint16_t trs_Euc; /* time required for enhanced erase */
+ // 91
+ uint16_t cur_apm_values; /* current APM values */
+ // 92
+ uint16_t mprc; /* master password revision code */
+ // 93
+ uint16_t hw_config; /* hardware config (word 93)
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 0: Shall be ONE
+ */
+ // 94
+ uint16_t acoustic;
+ // 95
+ uint16_t msrqs; /* min stream request size */
+ // 96
+ uint16_t sxfert; /* stream transfer time */
+ // 97
+ uint16_t sal; /* stream access latency */
+ // 98
+ uint32_t spg; /* stream performance granularity */
+ // 100
+ uint64_t lba_capacity_2; /* 48-bit total number of sectors */
+ // 104
+ uint16_t rsvd9[22];
+
+ // 126
+ uint16_t last_lun;
+ // 127
+ uint16_t feature_set; // Removable Media Notification
+
+ // 128
+ uint16_t dlf; /* device lock function
+ * 15:9 reserved
+ * 8 security level 1:max 0:high
+ * 7:6 reserved
+ * 5 enhanced erase
+ * 4 expire
+ * 3 frozen
+ * 2 locked
+ * 1 en/disabled
+ * 0 capability
+ */
+ // 129
+ uint16_t csfo; /* current set features options
+ * 15:4 reserved
+ * 3: auto reassign
+ * 2: reverting
+ * 1: read-look-ahead
+ * 0: write cache
+ */
+
+ // 130
+ uint16_t rsvd10[30];
+
+ // 160
+ uint16_t cfa_power;
+
+ // 161
+ uint16_t cfa[15];
+ // 176
+ uint16_t cur_media_ser_num[30];
+ // 206
+ uint16_t rsvd11[49];
+ // 255
+ uint16_t integrity; /* 15:8 Checksum
+ * 7:0 Signature
+ */
+
} __attribute__((packed));
} __attribute__((packed));
#include <palacios/vmm.h>
#include <devices/ide.h>
+#include <devices/pci.h>
#include "ide-types.h"
#include "atapi-types.h"
#define SEC_ADDR_REG_PORT 0x377
+#define PRI_DMA_CMD_PORT 0xc000
+#define PRI_DMA_STATUS_PORT 0xc002
+#define PRI_DMA_PRD_PORT0 0xc004
+#define PRI_DMA_PRD_PORT1 0xc005
+#define PRI_DMA_PRD_PORT2 0xc006
+#define PRI_DMA_PRD_PORT3 0xc007
+
+#define SEC_DMA_CMD_PORT 0xc008
+#define SEC_DMA_STATUS_PORT 0xc00a
+#define SEC_DMA_PRD_PORT0 0xc00c
+#define SEC_DMA_PRD_PORT1 0xc00d
+#define SEC_DMA_PRD_PORT2 0xc00e
+#define SEC_DMA_PRD_PORT3 0xc00f
+
#define DATA_BUFFER_SIZE 2048
+static const char * ide_pri_port_strs[] = {"PRI_DATA", "PRI_FEATURES", "PRI_SECT_CNT", "PRI_SECT_NUM",
+ "PRI_CYL_LOW", "PRI_CYL_HIGH", "PRI_DRV_SEL", "PRI_CMD",
+ "PRI_CTRL", "PRI_ADDR_REG"};
+
+
+static const char * ide_sec_port_strs[] = {"SEC_DATA", "SEC_FEATURES", "SEC_SECT_CNT", "SEC_SECT_NUM",
+ "SEC_CYL_LOW", "SEC_CYL_HIGH", "SEC_DRV_SEL", "SEC_CMD",
+ "SEC_CTRL", "SEC_ADDR_REG"};
+
+static const char * ide_dma_port_strs[] = {"PRI_DMA_CMD", NULL,
+ "PRI_DMA_STATUS", NULL,
+ "PRI_DMA_PRD0", "PRI_DMA_PRD1",
+ "PRI_DMA_PRD2", "PRI_DMA_PRD3",
+ "SEC_DMA_CMD", NULL,
+ "SEC_DMA_STATUS", NULL,
+ "SEC_DMA_PRD0","SEC_DMA_PRD1",
+ "SEC_DMA_PRD2","SEC_DMA_PRD3"};
+
+
+
+static inline const char * io_port_to_str(uint16_t port) {
+ if ((port >= PRI_DATA_PORT) && (port <= PRI_CMD_PORT)) {
+ return ide_pri_port_strs[port - PRI_DATA_PORT];
+ } else if ((port >= SEC_DATA_PORT) && (port <= SEC_CMD_PORT)) {
+ return ide_sec_port_strs[port - SEC_DATA_PORT];
+ } else if ((port == PRI_CTRL_PORT) || (port == PRI_ADDR_REG_PORT)) {
+ return ide_pri_port_strs[port - PRI_CTRL_PORT + 8];
+ } else if ((port == SEC_CTRL_PORT) || (port == SEC_ADDR_REG_PORT)) {
+ return ide_sec_port_strs[port - SEC_CTRL_PORT + 8];
+ } else if ((port >= PRI_DMA_CMD_PORT) && (port <= SEC_DMA_PRD_PORT3)) {
+ return ide_dma_port_strs[port - PRI_DMA_CMD_PORT];
+ }
+ return NULL;
+}
+
+
+
static const char * ide_dev_type_strs[] = {"HARDDISK", "CDROM", "NONE"};
struct atapi_irq_flags irq_flags;
} __attribute__((packed));
- uint8_t sector_num; // 0x1f3,0x173
+ union {
+ uint8_t sector_num; // 0x1f3,0x173
+ uint8_t lba0;
+ };
union {
uint16_t cylinder;
+ uint16_t lba12;
+
struct {
uint8_t cylinder_low; // 0x1f4,0x174
uint8_t cylinder_high; // 0x1f5,0x175
} __attribute__((packed));
+ struct {
+ uint8_t lba1;
+ uint8_t lba2;
+ } __attribute__((packed));
+
+
// The transfer length requested by the CPU
uint16_t req_len;
} __attribute__((packed));
+ struct ide_dma_cmd_reg dma_cmd;
+ struct ide_dma_status_reg dma_status;
+ uint32_t dma_prd_addr;
};
int irq; // this is temporary until we add PCI support
+ struct pci_device * pci_dev;
+
// Control Registers
struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
};
struct ide_internal {
struct ide_channel channels[2];
+ struct vm_device * pci;
+ struct pci_device * busmaster_pci;
};
static inline int get_channel_index(ushort_t port) {
if (((port & 0xfff8) == 0x1f0) ||
- ((port & 0xfffe) == 0x3f6)) {
+ ((port & 0xfffe) == 0x3f6) ||
+ ((port & 0xfff8) == 0xc000)) {
return 0;
} else if (((port & 0xfff8) == 0x170) ||
- ((port & 0xfffe) == 0x376)) {
+ ((port & 0xfffe) == 0x376) ||
+ ((port & 0xfff8) == 0xc008)) {
return 1;
}
#include "atapi.h"
+static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+ struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+ struct ide_channel * channel = get_selected_channel(ide, port);
+ struct ide_drive * drive = get_selected_drive(channel);
+
+ if (length != 1) {
+ PrintError("IDE: Invalid Write length on IDE port %x\n", port);
+ return -1;
+ }
+
+ PrintDebug("IDE: Writing DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
+
+ switch (port) {
+ case PRI_DMA_CMD_PORT:
+ case SEC_DMA_CMD_PORT:
+ drive->dma_cmd.val = *(uint8_t *)src;
+ break;
+
+ case PRI_DMA_STATUS_PORT:
+ case SEC_DMA_STATUS_PORT:
+ drive->dma_status.val = *(uint8_t *)src;
+ break;
+
+ case PRI_DMA_PRD_PORT0:
+ case PRI_DMA_PRD_PORT1:
+ case PRI_DMA_PRD_PORT2:
+ case PRI_DMA_PRD_PORT3:
+ case SEC_DMA_PRD_PORT0:
+ case SEC_DMA_PRD_PORT1:
+ case SEC_DMA_PRD_PORT2:
+ case SEC_DMA_PRD_PORT3: {
+ uint_t addr_index = port & 0x3;
+ uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
+
+ addr_buf[addr_index] = *(uint8_t *)src;
+ break;
+ }
+ default:
+ PrintError("IDE: Invalid DMA Port (%x)\n", port);
+ return -1;
+ }
+
+ return length;
+}
+
+
+static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+ struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+ struct ide_channel * channel = get_selected_channel(ide, port);
+ struct ide_drive * drive = get_selected_drive(channel);
+
+ if (length != 1) {
+ PrintError("IDE: Invalid Write length on IDE port %x\n", port);
+ return -1;
+ }
+
+
+
+ switch (port) {
+ case PRI_DMA_CMD_PORT:
+ case SEC_DMA_CMD_PORT:
+ *(uint8_t *)dst = drive->dma_cmd.val;
+ break;
+
+ case PRI_DMA_STATUS_PORT:
+ case SEC_DMA_STATUS_PORT:
+ *(uint8_t *)dst = drive->dma_status.val;
+ break;
+
+ case PRI_DMA_PRD_PORT0:
+ case PRI_DMA_PRD_PORT1:
+ case PRI_DMA_PRD_PORT2:
+ case PRI_DMA_PRD_PORT3:
+ case SEC_DMA_PRD_PORT0:
+ case SEC_DMA_PRD_PORT1:
+ case SEC_DMA_PRD_PORT2:
+ case SEC_DMA_PRD_PORT3: {
+ uint_t addr_index = port & 0x3;
+ uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
+
+ *(uint8_t *)dst = addr_buf[addr_index];
+ break;
+ }
+ default:
+ PrintError("IDE: Invalid DMA Port (%x)\n", port);
+ return -1;
+ }
+
+ PrintDebug("IDE: Reading DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)dst);
+
+ return length;
+}
+
+
+
static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
struct ide_channel * channel = get_selected_channel(ide, port);
return -1;
}
- PrintDebug("IDE: Writing Command Port %x (val=%x)\n", port, *(uint8_t *)src);
+ PrintDebug("IDE: Writing Command Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
channel->cmd_reg = *(uint8_t *)src;
return -1;
}
- PrintDebug("IDE: Writing Standard Port %x (val=%x)\n", port, *(uint8_t *)src);
+ PrintDebug("IDE: Writing Standard Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
switch (port) {
return -1;
}
- PrintDebug("IDE: Reading Standard Port %x\n", port);
+ PrintDebug("IDE: Reading Standard Port %x (%s)\n", port, io_port_to_str(port));
if ((port == PRI_ADDR_REG_PORT) ||
drive->transfer_length = 0;
memset(drive->data_buf, 0, sizeof(drive->data_buf));
+ drive->dma_cmd.val = 0;
+ drive->dma_status.val = 0;
+ drive->dma_prd_addr = 0;
+
drive->private_data = NULL;
drive->cd_ops = NULL;
}
}
-static void init_ide_state(struct ide_internal * ide) {
- int i;
+/*
+static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) {
+ PrintError("IDE does not handle PCI config updates\n");
+ return -1;
+}
+*/
+
+static int pci_bar_update(struct pci_device * pci_dev, uint_t bar) {
+ PrintError("IDE does not support bar updates\n");
+ return -1;
+}
+
+
+static int init_ide_state(struct vm_device * dev) {
+ struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+ struct v3_pci_bar bars[6];
+ struct pci_device * pci_dev = NULL;
+ int i, j;
for (i = 0; i < 2; i++) {
init_channel(&(ide->channels[i]));
// JRL: this is a terrible hack...
ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
+
+ for (j = 0; j < 6; j++) {
+ bars[j].type = PCI_BAR_NONE;
+ bars[j].mem_hook = 0;
+ bars[j].num_pages = 0;
+ bars[j].bar_update = NULL;
+ }
+
+
+ bars[4].type = PCI_BAR_IO;
+ bars[4].bar_update = pci_bar_update;
+
+ pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
+ NULL, NULL, NULL, dev);
+
+ if (pci_dev == NULL) {
+ PrintError("Failed to register IDE BUS %d with PCI\n", i);
+ return -1;
+ }
+
+ ide->channels[i].pci_dev = pci_dev;
+
+ pci_dev->config_header.vendor_id = 0x1095;
+ pci_dev->config_header.device_id = 0x0646;
+ pci_dev->config_header.revision = 0x8f07;
+ pci_dev->config_header.subclass = 0x01;
+ pci_dev->config_header.class = 0x01;
}
+
+
+
+ /* Register PIIX3 Busmaster PCI device */
+ for (j = 0; j < 6; j++) {
+ bars[j].type = PCI_BAR_NONE;
+ bars[j].mem_hook = 0;
+ bars[j].num_pages = 0;
+ bars[j].bar_update = NULL;
+ }
+
+ pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "PIIX3 IDE", -1, bars,
+ NULL, NULL, NULL, dev);
+
+
+ ide->busmaster_pci = pci_dev;
+
+ pci_dev->config_header.vendor_id = 0x8086;
+ pci_dev->config_header.device_id = 0x7010;
+ pci_dev->config_header.revision = 0x80;
+ pci_dev->config_header.subclass = 0x01;
+ pci_dev->config_header.class = 0x01;
+
+
+ return 0;
}
static int init_ide(struct vm_device * dev) {
- struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+ //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
PrintDebug("IDE: Initializing IDE\n");
- init_ide_state(ide);
+ if (init_ide_state(dev) == -1) {
+ PrintError("Failed to initialize IDE state\n");
+ return -1;
+ }
+
- v3_dev_hook_io(dev, PRI_CTRL_PORT,
- &read_port_std, &write_port_std);
v3_dev_hook_io(dev, PRI_DATA_PORT,
&ide_read_data_port, &write_data_port);
v3_dev_hook_io(dev, PRI_CMD_PORT,
&read_port_std, &write_cmd_port);
-
- v3_dev_hook_io(dev, SEC_CTRL_PORT,
- &read_port_std, &write_port_std);
-
v3_dev_hook_io(dev, SEC_DATA_PORT,
&ide_read_data_port, &write_data_port);
v3_dev_hook_io(dev, SEC_FEATURES_PORT,
v3_dev_hook_io(dev, SEC_CMD_PORT,
&read_port_std, &write_cmd_port);
+
+ v3_dev_hook_io(dev, PRI_CTRL_PORT,
+ &read_port_std, &write_port_std);
+
+ v3_dev_hook_io(dev, SEC_CTRL_PORT,
+ &read_port_std, &write_port_std);
v3_dev_hook_io(dev, SEC_ADDR_REG_PORT,
v3_dev_hook_io(dev, PRI_ADDR_REG_PORT,
&read_port_std, &write_port_std);
+
+
+ v3_dev_hook_io(dev, PRI_DMA_CMD_PORT,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, PRI_DMA_STATUS_PORT,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+
+
+ v3_dev_hook_io(dev, SEC_DMA_CMD_PORT,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, SEC_DMA_STATUS_PORT,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+ v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0,
+ &read_dma_port, &write_dma_port);
+
return 0;
}
};
-struct vm_device * v3_create_ide() {
+struct vm_device * v3_create_ide(struct vm_device * pci) {
struct ide_internal * ide = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));
struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
- // ide->pci = pci;
+ ide->pci = pci;
PrintDebug("IDE: Creating IDE bus x 2\n");