Remaining SATA (and other) issues

Søren Schmidt sos at deepcore.dk
Thu Nov 8 01:43:33 PST 2007


Alexander Sabourenkov wrote:
> Please test this:
>
> http://lxnt.info/tx4/freebsd/chipinit.patch
> http://lxnt.info/tx4/freebsd/dma.patch
>
OK, some of that patch is wrong and break older chipsets, lets break it 
down:

@@ -3265,12 +3265,26 @@
 	    stat_reg = 0x60;
 	    break;
 	}
-
-	/* prime fake interrupt register */
-	ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff);

You cant remove this, ATA uses the 0x54 reg to store interrupts, its a gen purpose reg on the promises, this initialization is neededed.

-
-	/* clear SATA status */
-	ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff);
+	{
+	    const int PDC_FLASHCTL = 0x44;
+	    const int PDC_HOTPLUG  = 0x60;
+	    int tmp;
+	    
+	    /* enable BMR_BURST */
+	    tmp = ATA_INL(ctlr->r_res2, PDC_FLASHCTL);
+	    tmp |= 0x2000;
+	    ATA_OUTL(ctlr->r_res2, PDC_FLASHCTL, tmp);

That part might be relevant, but the registers are only valid on newer promise chips (those I call PRSATA2).

+	    
+	    /* clear plug/unplug flags */
+	    tmp = ATA_INL(ctlr->r_res2, PDC_HOTPLUG);
+	    tmp |= 0xff;
+	    ATA_OUTL(ctlr->r_res2, PDC_HOTPLUG, tmp);
+
+	    /* unmask plug/unplug ints */
+	    tmp = ATA_INL(ctlr->r_res2, PDC_HOTPLUG);
+	    tmp &= 0xff00ffff;
+	    ATA_OUTL(ctlr->r_res2, PDC_HOTPLUG, tmp);

This part is wrong for older promise chips, as the port# is different.
I also have a hard time seeing that this couldd change anything since the registers are reset etc "my way" on each interrupt.
Besides you *do not* want to pass the other bits through, they shoudl be masked off and always written as 0's.

So my stance at this would be something like:

+++ ata-chipset.c	8 Nov 2007 10:43:00 -0000
@@ -3288,9 +3288,13 @@
 	/* prime fake interrupt register */
 	ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff);
 
-	/* clear SATA status */
+	/* clear SATA status and unmask interrupts */
 	ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff);
 
+	/* enable "long burst lenght" on gen2 chips */
+	if ((ctlr->chip->cfg2 == PRSATA2) || (ctlr->chip->cfg2 == PRCMBO2))
+	    ATA_OUTL(ctlr->r_res2, 0x44, ATA_INL(ctlr->r_res2, 0x44) | 0x2000);
+
 	ctlr->allocate = ata_promise_mio_allocate;
 	ctlr->reset = ata_promise_mio_reset;
 	ctlr->dmainit = ata_promise_mio_dmainit;

The DMA table part I'll look into next, that one seems important, its just not enough in itself.

However I still need to find a way to reproduce, still hunting that one....

-Søren




More information about the freebsd-current mailing list