Bus master bug...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Sam Palmer

Bus master bug...

Post by Sam Palmer »

I've tried to do reading/writing on my hdd's with bus master operation for weeks now, and it just doesn't work. I really hope you guys can give me some help here...

The problem is simply that no interrupt is generated after I started the bus master operation, if I use for example read sectors instead of read dma an interrupt is generated and it seems to work fine. A strange thing is that if I try to read from status/alt. status or any other ATA register more then a very short time after bus master operation is started the computer totally locks! I have followed every step in the ATA-4 documentation and in my chip set documentation (Intel 440BX) but nothing works. My hdd's are a Seagate ST34321A (ATA-3) and a IBM-DTLA-307030 (ATA-4) both connected to primary channel. Identify device command shows that ultra-dma mode 2 is selected for both of them and UDMACTL register in chipset says ultra-dma is selected. BUT - the Drive 0/1 DMA Capable bits in bus master ide status register are both 0.

I've checked all the values in my variables carefully and I've tried to change around a lot but with no success. So what have I forgotten?

==========================================================================
/* set prd pointer... */
outl(io_base+4,(unsigned)(channel->prd));

/* set read or write bit */
outb(io_base,((char)(read_or_write<<3))|(inb(io_base)&0xF7));

/* clear IDE interrupt status and IDE DMA error */
outb(io_base+2,0x6);

/* device select with delay (temporary solution...), add 4 highest lba bits */
while(inb(command_block+7)&0x88);
outb(command_block+6,(char)((channel->dev_select<<4)|0x40|(lba>>24)));
while(test++ > 10000)
while(inb(command_block+7)&0x88);

/* rest of lba address... */
outb(command_block+5,(char)(lba>>16));
outb(command_block+4,(char)(lba>>8));
outb(command_block+3,(char)(lba));

/* sector count, 128 or 256 sectors */
outb(command_block+2,(char)(blocks_to_read<<7));

/* the command... */
outb(command_block+7,read_or_write?WRITE_DMA:READ_DMA);

/* start bus master */
outb(io_base,((char)(read_or_write<<3))|0x01|(inb(io_base)&0xF7));
==========================================================================

io_base for primary channel is 0x1020, command_block 0x01F0 and control_block 0x03F4. PRD table is aligned on 64KB boundary and the memory regions for reading/writing also.
Post Reply