Subject: Re: HPT366 (UDMA/66 patch)
To: Manuel Bouyer <>
From: Roger Brooks <>
List: current-users
Date: 03/10/2000 14:40:46
On Thu, 9 Mar 2000, Manuel Bouyer wrote:

>So some comments on the code:
>Content-Description: UDMA/66 patch for HPT366
>> +                 /* add timing values, setup DMA if needed */
>> +                 tim = hpt366_data_tim_pio[drvp->PIO_mode];
>> +                 if (drvp->drive_flags & DRIVE_DMA) {
>> +                         /*
>> +                          * use Multiword DMA.
>> +                          * Timings will be used for both PIO and DMA, so adjust
>> +                          * DMA mode if needed
>> +                          */
>This is not needed if you're using Ultra-DMA. You could do:
>                 if (drvp->drive_flags & DRIVE_UDMA) {
>                         tim = hpt366_data_tim_udma[drvp->DMA_mode];
>                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
>                 } else if (drvp->drive_flags & DRIVE_DMA) {
>                         /*
>                          * use Multiword DMA.
>                          * Timings will be used for both PIO and DMA, so adjust
>                          * DMA mode if needed
>                          */
>			  [...]

Yes, I know this needs a bit of tidying up, but I was waiting until I'd
sorted out what combinations of master/slave modes work in case I had
to look at modes for both drives first (like some of the Intel chips).
Last night I sorted out a problem (originating from a typo in the Linux
driver), and I can now get two drives on the same channel to work.

I put a UDMA mode 2 slave and a UDMA mode 4 master on the same channel.
Monitoring with iostat showed some interesting behaviour.  Reading a
raw partition from the mode 2 drive gave a data rate of ~9 MB/s, while
the mode 4 drive gave ~25 MB/s.  It so happened that the partition which
I chose on the mode 2 drive was much smaller than the other one and so
finished first.  What I observed was

    Start reading from mode 4 drive - iostat shows 25 MB/s
    Start reading from mode 2 drive - mode 4 drive slows down, so both
    are at 9 MB/sec
    Finish reading from mode 2 drive - mode 4 drive goes back to 25 MB/sec.

I also added the chip tuning tables for 25 MHz and 40 MHz PCI bus speeds
from the Linux driver.  I'm not completely convinced that this stuff is
actually needed, as up to now the timing register always seems to contain
the right value already.  The info Highpoint WWW site does say it's
self-tuning.  Feedback from anyone with the unlikely combination of a
machine with a 25 MHz PCI bus (an old 486 system?) and an Abit Hot-Rod
PCI card would be interesting.

But I STILL can't get both channels to work at the same time.

>> + #if 0
>> + 	u_int8_t dmastat;
>> + 
>> + 	/*
>> + 	 * FreeBSD has this code to avoid calling interrupt handler with
>> + 	 * other channel, but I don't think it's needed in NetBSD.
>> + 	 */
>> + 	dmastat = pciide_pci_read( sc->sc_pc, sc->sc_tag, IDEDMA_CTL );
>> + 	if( !(dmastat & IDEDMA_CTL_INTR) )
>> + 		return 0;
>> + 	pciide_pci_write( sc->sc_pc, sc->sc_tag, IDEDMA_CTL, dmastat );
>Hum. I think this is really needed !
>Look at pdc202xx_pci_intr() for example (although as you've a single-channel
>attachemement the above code should be enouth).
>I suspect that under some conditions a hard hang can occur if we read the
>status register before IRQ occured (this may be related to some controllers
>doing funny things with registers). We can also lose interrupt because of
>this. This can only happen with interrupt sharing, so it's not needed for
>controllers in legaty mode.

But doesn't/shouldn't wdcintr check that a transfer has been started on
the channel before trying to read the status register?  But this doesn't
help does it?  If both channels share an IRQ, and both have a transfer
in progress, then the handler gets called once for each channel, and has
to read the status register to see if that channel caused the interrupt.
But if reading the status register for a channel which hasn't completed
causes a hangup, then how on earth can you possibly manage to do
concurrent transfers on both channels?

There's also a kernel configuration option in the Linux driver for
"fast interrupt prediction".  Does anyone know what this is?  I've
added code to allow it to be turned off/on from the flags on the
pciide config file entry, but haven't yet tried turning it on to
see if it helps.

>Also, as a general note I prefer to #define registers names and contents
>in pciide_xxx_reg.h and use symbolic names in the driver :)

I quite agree!  I was rather disappointed (the polite way of putting it :-))
when I started looking at the code for the Linux driver.  Hex constants
scattered all over the place...  and a twisty maze of little functions,
all with very similar names.

I've emailed support at Highpoint to ask for documentation, but haven't got
a reply yet.  Unless/until I get some docs, I don't know exactly what the
registers do.  For example, if the 0x02 bit is set in register 0x5a, this
means a UDMA/33 cable is connected, but I've no idea what (if anything)
the other bits do.  So if I start trying to give symbolic names to registers
and the bits therein I'm in a similar situation to Adam naming the beasts
("... and whatever he called each one, that was its name" :-)).

In the absence of documentation, if I don't make progress on getting both
channels to work I'll consider installing Linux just to see if it actually
works with their driver.

I need to do some work on my house this weekend, but I'll try to find time
to tidy the code a little and post a revised patch in a couple of days
so that anyone with a HPT366 can at least use one channel.


Roger Brooks (Systems Programmer),          |  Email:
Computing Services Dept,                    |  Tel:   +44 151 794 4441
The University of Liverpool,                |  Fax:   +44 151 794 4442
PO Box 147, Liverpool L69 3BX, UK           |