X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fide.c;h=17d94612fd35072327775a347ca0fd14670727e8;hb=a623576ca0618c548af2b96308e996eb32158c49;hp=80f76b298e039e1c22b266be86755dc31f1fd778;hpb=7ddf7f8c9b007c3405146e001d9f3689723f7d4d;p=palacios.releases.git diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c index 80f76b2..17d9461 100644 --- a/palacios/src/devices/ide.c +++ b/palacios/src/devices/ide.c @@ -159,7 +159,6 @@ struct ide_drive { uint8_t data_buf[DATA_BUFFER_SIZE]; - uint32_t num_cylinders; uint32_t num_heads; uint32_t num_sectors; @@ -365,6 +364,37 @@ static int dma_write(struct vm_device * dev, struct ide_channel * channel); #include "ata.h" +#ifdef DEBUG_IDE +static void print_prd_table(struct vm_device * dev, struct ide_channel * channel) { + struct ide_dma_prd prd_entry; + int index = 0; + + PrintDebug("Dumping PRD table\n"); + + while (1) { + uint32_t prd_entry_addr = channel->dma_prd_addr + (sizeof(struct ide_dma_prd) * index); + int ret; + + ret = read_guest_pa_memory(dev->vm, prd_entry_addr, sizeof(struct ide_dma_prd), (void *)&prd_entry); + + if (ret != sizeof(struct ide_dma_prd)) { + PrintError("Could not read PRD\n"); + return; + } + + PrintDebug("\tPRD Addr: %x, PRD Len: %d, EOT: %d\n", + prd_entry.base_addr, prd_entry.size, prd_entry.end_of_table); + + if (prd_entry.end_of_table) { + break; + } + + index++; + } + + return; +} +#endif /* IO Operations */ static int dma_read(struct vm_device * dev, struct ide_channel * channel) { @@ -376,6 +406,9 @@ static int dma_read(struct vm_device * dev, struct ide_channel * channel) { // Read in the data buffer.... // Read a sector/block at a time until the prd entry is full. +#ifdef DEBUG_IDE + print_prd_table(dev, channel); +#endif PrintDebug("DMA read for %d bytes\n", bytes_left); @@ -385,80 +418,91 @@ static int dma_read(struct vm_device * dev, struct ide_channel * channel) { uint_t prd_bytes_left = 0; uint_t prd_offset = 0; int ret; - + PrintDebug("PRD table address = %x\n", channel->dma_prd_addr); - + ret = read_guest_pa_memory(dev->vm, prd_entry_addr, sizeof(struct ide_dma_prd), (void *)&prd_entry); - + if (ret != sizeof(struct ide_dma_prd)) { PrintError("Could not read PRD\n"); return -1; } - + PrintDebug("PRD Addr: %x, PRD Len: %d, EOT: %d\n", prd_entry.base_addr, prd_entry.size, prd_entry.end_of_table); - + // loop through the PRD data.... - + prd_bytes_left = prd_entry.size; - - + + while (prd_bytes_left > 0) { uint_t bytes_to_write = 0; - + if (drive->drive_type == IDE_DISK) { bytes_to_write = (prd_bytes_left > IDE_SECTOR_SIZE) ? IDE_SECTOR_SIZE : prd_bytes_left; - - + + if (ata_read(dev, channel, drive->data_buf, 1) == -1) { PrintError("Failed to read next disk sector\n"); return -1; } } else if (drive->drive_type == IDE_CDROM) { - bytes_to_write = (prd_bytes_left > ATAPI_BLOCK_SIZE) ? ATAPI_BLOCK_SIZE : prd_bytes_left; - - if (atapi_read_chunk(dev, channel) == -1) { - PrintError("Failed to read next disk sector\n"); + if (atapi_cmd_is_data_op(drive->cd_state.atapi_cmd)) { + bytes_to_write = (prd_bytes_left > ATAPI_BLOCK_SIZE) ? ATAPI_BLOCK_SIZE : prd_bytes_left; + + if (atapi_read_chunk(dev, channel) == -1) { + PrintError("Failed to read next disk sector\n"); + return -1; + } + } else { + PrintDebug("DMA of command packet\n"); + PrintError("How does this work???\n"); return -1; + bytes_to_write = (prd_bytes_left > bytes_left) ? bytes_left : prd_bytes_left; + prd_bytes_left = bytes_to_write; } } - + PrintDebug("Writing DMA data to guest Memory ptr=%p, len=%d\n", (void *)(addr_t)(prd_entry.base_addr + prd_offset), bytes_to_write); drive->current_lba++; - + ret = write_guest_pa_memory(dev->vm, prd_entry.base_addr + prd_offset, bytes_to_write, drive->data_buf); - + if (ret != bytes_to_write) { PrintError("Failed to copy data into guest memory... (ret=%d)\n", ret); return -1; } PrintDebug("\t DMA ret=%d, (prd_bytes_left=%d) (bytes_left=%d)\n", ret, prd_bytes_left, bytes_left); - + drive->transfer_index += ret; prd_bytes_left -= ret; prd_offset += ret; bytes_left -= ret; - } - - channel->dma_tbl_index++; - + + channel->dma_tbl_index++; + if (drive->drive_type == IDE_DISK) { if (drive->transfer_index % IDE_SECTOR_SIZE) { PrintError("We currently don't handle sectors that span PRD descriptors\n"); return -1; } } else if (drive->drive_type == IDE_CDROM) { - if (drive->transfer_index % ATAPI_BLOCK_SIZE) { - PrintError("We currently don't handle ATAPI BLOCKS that span PRD descriptors\n"); - return -1; + if (atapi_cmd_is_data_op(drive->cd_state.atapi_cmd)) { + if (drive->transfer_index % ATAPI_BLOCK_SIZE) { + PrintError("We currently don't handle ATAPI BLOCKS that span PRD descriptors\n"); + PrintError("transfer_index=%d, transfer_length=%d\n", + drive->transfer_index, drive->transfer_length); + return -1; + } } } - - + + if ((prd_entry.end_of_table == 1) && (bytes_left > 0)) { PrintError("DMA table not large enough for data transfer...\n"); return -1; @@ -1400,6 +1444,7 @@ static int init_ide(struct vm_device * dev) { return -1; } + PrintDebug("Connecting to IDE IO ports\n"); v3_dev_hook_io(dev, PRI_DATA_PORT, &ide_read_data_port, &write_data_port); @@ -1459,6 +1504,8 @@ static int init_ide(struct vm_device * dev) { struct pci_device * pci_dev = NULL; int i; + PrintDebug("Connecting IDE to PCI bus\n"); + for (i = 0; i < 6; i++) { bars[i].type = PCI_BAR_NONE; } @@ -1489,9 +1536,9 @@ static int init_ide(struct vm_device * dev) { pci_dev->config_header.device_id = 0x7010; pci_dev->config_header.revision = 0x00; - pci_dev->config_header.prog_if = 0x80; - pci_dev->config_header.subclass = 0x01; - pci_dev->config_header.class = 0x01; + pci_dev->config_header.prog_if = 0x80; // Master IDE device + pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_IDE; + pci_dev->config_header.class = PCI_CLASS_STORAGE; pci_dev->config_header.command = 0; pci_dev->config_header.status = 0x0280; @@ -1501,6 +1548,8 @@ static int init_ide(struct vm_device * dev) { } + PrintDebug("IDE Initialized\n"); + return 0; } @@ -1523,18 +1572,23 @@ static struct vm_device_ops dev_ops = { struct vm_device * v3_create_ide(struct vm_device * pci_bus, struct vm_device * southbridge_dev) { 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_bus = pci_bus; - if (ide->southbridge) { - ide->southbridge = (struct v3_southbridge *)(southbridge_dev->private_data); - } else { - ide->southbridge = NULL; + memset(ide, 0, sizeof(struct ide_internal)); + + if (pci_bus != NULL) { + if (southbridge_dev == NULL) { + PrintError("PCI Enabled BUT southbridge is NULL\n"); + return NULL; + } + + ide->pci_bus = pci_bus; + ide->southbridge = (struct v3_southbridge *)(southbridge_dev->private_data); } + PrintDebug("IDE: Creating IDE bus x 2\n"); - return device; + return v3_create_device("IDE", &dev_ops, ide); }