git: 9front

Download patch

ref: 160fb6f6afd1ff8937a41cd6ba1bc9a8b67845b4
parent: 57ac229f4618a2ba31dd3e8fdee9431f3853f362
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Aug 27 17:20:20 EDT 2017

sdiahci: Intel 200 Series Chipset Family PCH support (thanks aiju)

we used to tweak arround in the ICH registers for all intel controllers,
which is wrong, as the 200 series has different magic registes. see
the datasheet:

https://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-2.html

this caused the clocks to be disabled for the 6th port causing a full
machine lockup touching the 6th port registers.

the next problem was that aiju's bios disabled the unused ports somehow
but didnt clear ther PI bits, so that they would stay in Sbist status even
after a port reset. so the port would get stuck in the Dportreset state
forever. the fix for this was to use a one second timeout for the
port reset procedure.

--- a/sys/src/9/pc/sdiahci.c
+++ b/sys/src/9/pc/sdiahci.c
@@ -353,7 +353,7 @@
 		esleep(ms);
 }
 
-static int
+static void
 ahciportreset(Aportc *c, uint mode)
 {
 	ulong *cmd, i;
@@ -372,7 +372,6 @@
 	p->sctl = 3*Aipm | 0*Aspd | Adet;
 	delay(1);
 	p->sctl = 3*Aipm | mode*Aspd;
-	return 0;
 }
 
 static int
@@ -788,12 +787,6 @@
 }
 
 static int
-intel(Ctlr *c)
-{
-	return c->pci->vid == 0x8086;
-}
-
-static int
 ignoreahdrs(Drive *d)
 {
 	return d->portm.feat & Datapi && d->ctlr->type == Tsb600;
@@ -1011,9 +1004,9 @@
 
 enum {
 	Nms		= 256,
+	Mcomrwait	=  1*1024/Nms - 1,
 	Mphywait	=  2*1024/Nms - 1,
 	Midwait		= 16*1024/Nms - 1,
-	Mcomrwait	= 64*1024/Nms - 1,
 };
 
 static void
@@ -1110,6 +1103,7 @@
 			else
 				d->mode--;
 			if(d->mode == DMautoneg){
+				d->wait = 0;
 				d->state = Dportreset;
 				goto portreset;
 			}
@@ -1141,7 +1135,6 @@
 	case Doffline:
 		if(d->wait++ & Mcomrwait)
 			break;
-		/* fallthrough */
 	case Derror:
 	case Dreset:
 		dprint("%s: reset [%s]: mode %d; status %.3ux\n",
@@ -1152,8 +1145,12 @@
 		break;
 	case Dportreset:
 portreset:
-		if(d->wait++ & 0xff && (s & Iactive) == 0)
+		if(d->wait++ & Mcomrwait)
 			break;
+		if(d->wait > Mcomrwait && (s & Iactive) == 0){
+			d->state = Dnull;	/* stuck in portreset */
+			break;
+		}
 		dprint("%s: portreset [%s]: mode %d; status %.3ux\n",
 			dnam(d), diskstates[d->state], d->mode, s);
 		d->portm.flag |= Ferror;
@@ -1957,20 +1954,6 @@
 	return r->status = SDeio;
 }
 
-/*
- * configure drives 0-5 as ahci sata  (c.f. errata)
- */
-static int
-iaahcimode(Pcidev *p)
-{
-	uint u;
-
-	u = pcicfgr16(p, 0x92);
-	dprint("ahci: %T: iaahcimode %.2ux %.4ux\n", p->tbdf, pcicfgr8(p, 0x91), u);
-	pcicfgw16(p, 0x92, u | 0xf);	/* ports 0-15 */
-	return 0;
-}
-
 enum{
 	Ghc	= 0x04/4,	/* global host control */
 	Pi	= 0x0c/4,	/* ports implemented */
@@ -1983,14 +1966,20 @@
 static void
 iasetupahci(Ctlr *c)
 {
+	if(c->type != Tich)
+		return;
+
 	pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~Cmddec);
 	pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~Cmddec);
 
 	c->lmmio[Ghc] |= Ahcien;
-	c->lmmio[Pi] = (1 << 6) - 1;	/* 5 ports (supposedly ro pi reg) */
+	c->lmmio[Pi] = (1 << 6) - 1;	/* 6 ports (supposedly ro pi reg) */
 
 	/* enable ahci mode; from ich9 datasheet */
 	pcicfgw16(c->pci, 0x90, 1<<6 | 1<<5);
+
+	/* configure drives 0-5 as ahci sata  (c.f. errata) */
+	pcicfgw16(c->pci, 0x92, pcicfgr16(c->pci, 0x92) | 0xf);
 }
 
 static void
@@ -2187,11 +2176,10 @@
 		c->sdev = s;
 
 		ahcihandoff((Ahba*)c->mmio);
-		if(intel(c) && p->did != 0x2681)
+		if(p->vid == 0x8086)
 			iasetupahci(c);
-//		ahcihbareset((Ahba*)c->mmio);
 		nunit = ahciconf(c);
-		if(intel(c) && iaahcimode(p) == -1 || nunit < 1){
+		if(nunit < 1){
 			vunmap(c->mmio, p->mem[Abar].size);
 			continue;
 		}
--