Hi,
Thanks a lot for the reply.
I have enabled the pci_ide debug option.
I did some experiments that might help helping me:)
Now for virtualbox my OS run with no problems and with the expected functionalities.
I have downloaded bochs 2.6.9 (the latest) and I have tried running my OS on the three environments Bochs 2.6.8, 2.6.9, and Qemu.
First of all here is the code portion that has the problem:
Code: Select all
uint8_t readDMADiskSectors (ATADisk * p_ataDisk,uint64_t addr,uint32_t p_sector_count)
{
uint16_t io_port = p_ataDisk->io_port;
uint32_t dma_port_address = p_ataDisk->dma_port_address;
uint8_t * dma_phy_address = p_ataDisk->dma_phy_address;
uint32_t * ptr = (uint32_t *)p_ataDisk->prdt;
memset(dma_phy_address,0,0x2000000);
uint32_t sectors = p_sector_count;
uint16_t i = 0;
for ( ;sectors > 0; i+= 2 )
{
if ( sectors > 128 )
{
ptr[i] = (uint64_t) dma_phy_address+ ((i/2) * 0x10000);
ptr[i+1] = 0x00000000 | (128 * 0x200);
sectors -= 128;
}
else if (sectors <= 128)
{
ptr[i] = (uint64_t) dma_phy_address+ ((i/2) * 0x10000);
ptr[i+1] = 0x80000000 | (sectors * 0x200);
sectors = 0;
}
}
outportb(dma_port_address+BM0_COMMAND+p_ataDisk->bm_offset,0);
outportb(dma_port_address+BM0_STATUS+p_ataDisk->bm_offset,(1<<2)|(1 << 1));
outportl(dma_port_address+BM0_ADDRESS+p_ataDisk->bm_offset,(uint32_t)ptr);
uint8_t select = (0xE0 | (p_ataDisk->slavebit << 4));
if (kernel.dmaBuffer.current_select != select )
{
if ( p_ataDisk->lba48)
{
printk ("reading lba48\n");
outportb(io_port + ATA_REG_HDDEVSEL,select);
}
else outportb(io_port + ATA_REG_HDDEVSEL, (select | ((addr >> 24) & 0x0F)));
ide_400ns_delay(p_ataDisk);
kernel.dmaBuffer.current_select = select;
}
printk ("io_port: %x\n",io_port);
outportb(io_port + ATA_REG_FEATURES, 0x00);
outportb(io_port + ATA_REG_SECCOUNT1, (uint8_t)(p_sector_count >> 8));
outportb(io_port + ATA_REG_LBA3, (uint8_t)(addr >> 24));
outportb(io_port + ATA_REG_LBA4, (uint8_t)(addr >> 32));
outportb(io_port + ATA_REG_LBA5, (uint8_t)(addr >> 40));
outportb(io_port + ATA_REG_SECCOUNT0,(uint8_t) p_sector_count);
outportb(io_port + ATA_REG_LBA0, (uint8_t)addr);
outportb(io_port + ATA_REG_LBA1, (uint8_t)(addr >> 8));
outportb(io_port + ATA_REG_LBA2, (uint8_t)(addr >> 16));
if ( p_ataDisk->lba48) outportb(io_port + ATA_REG_COMMAND, ATA_CMD_READ_DMA_EXT);
else outportb(io_port + ATA_REG_COMMAND, ATA_CMD_READ_DMA); // 0xC8 for reading
if (inportb(io_port + ATA_REG_STATUS))
{
for (uint64_t i = 0 ;;i++)
{
uint8_t status = inportb(io_port+ATA_REG_STATUS);
if ( (status & ATA_SR_BSY))
{
printk ("DMA status is BSY: %d\n",i);
continue;
}
else if(status & ATA_SR_ERR)
{
printk ("<<<<<< Error in readDMADiskSector: %x\n",status);
if (p_ataDisk->bm_offset == 0 ) outportb(ATA_PRIMARY_DCR_AS,0b00000000);
else outportb(ATA_SECONDARY_DCR_AS,0b00000000);
if ( p_ataDisk->slavebit )
outportb(io_port + ATA_REG_HDDEVSEL, ATA_SLAVE_DRV_SELECTOR);
else outportb(io_port + ATA_REG_HDDEVSEL, ATA_MASTER_DRV_SELECTOR);
ide_400ns_delay(p_ataDisk);
status = inportb(io_port+ATA_REG_STATUS);
kernel.dmaBuffer.current_select = 0;
return READ_DMA_FAIL;
}
else if ( status & ATA_SR_DRQ )break;
else printk ("%d:Something else: %d\n",i,status);
}
}
outportb(dma_port_address+BM0_COMMAND+p_ataDisk->bm_offset,(1 << 3)|(1 << 0));
return READ_DMA_SUCCESS;
}
Now, for bochs 2.6.9 everything works very well as virtualbox, and the pci_ide debug info shows the disk firing interrupts as expected after committing to the DMA command register.
On my already installed bochs 2.6.8 (the old one), still the ATA commands run successfully but the DMA does not fire the interrupts and the debug info stops at the debug line indicating that I have written successfully to the DMA command register to start the transfer.
Finally on qemu, It does not even go beyond the ATA extended read. After the read I get caught in the loop of checking the ATA status and never get out of it as the keeps on being busy and printing the busy message after each ata status read.
The disk I am trying to read from is the primary/slave ata.
I start my Qemu using the following command:
Code: Select all
qemu-system-x86_64 -cpu host -m 4096 -smp 4 -drive file=./boot.qcow2,if=ide,index=0,media=disk -drive file=./data.qcow2,if=ide,index=1,media=disk --enable-kvm
And I use the following bochsrc to start bochs in both versions.
Code: Select all
config_interface: textconfig
display_library: x
romimage: file=/home/kmsobh/crossenv/bochs-2.6.8/bios/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
debug: action=ignore, pci_ide=report
error: action=report
info: action=ignore #,ioapic=report #pci=report, pic=report, pci_ide=report
#debug: action=ignore , cpu1=report #, e1000=report, ioapic=report #memory=report #pci_ide=report
memory: guest=8192, host=2048
boot: disk
ata0-master: type=disk, path="./images/boot.raw"
ata0-slave: type=disk, path="./images/data.raw"
cpu: count=4, ips=10000000
cpuid: x86_64=1,apic=x2apic
plugin_ctrl: unmapped=0
One remark that I do not know if it is important or not is that bochs 2.6.8 starts and get the bochs emulator window much much faster than 2.6.9, and as soon as the emulation starts both progress at the same speed.
Please let me know if you can figure out the problem.
I appreciate any help,
Thanks a lot,
Karim.