Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Feb 2012 13:39:53 +0000 (UTC)
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r230865 - head/sys/dev/mvs
Message-ID:  <201202011339.q11DdrRY089245@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: raj
Date: Wed Feb  1 13:39:52 2012
New Revision: 230865
URL: http://svn.freebsd.org/changeset/base/230865

Log:
  Adjust mvs(4) to handle interrupt cause reg depending on the actual number of
  channels available
  
  - current code treats bits 4:7 in 'SATAHC interrupt mask' and 'SATAHC
    interrupt cause' as flags for SATA channels 2 and 3
  
  - for embedded SATA controllers (SoC) these bits have been marked as reserved
    in datasheets so far, but for some new and upcoming chips they are used for
    purposes other than SATA
  
  Submitted by:	Lukasz Plachno
  Reviewed by:	mav
  Obtained from:	Semihalf
  MFC after:	2 weeks

Modified:
  head/sys/dev/mvs/mvs.h
  head/sys/dev/mvs/mvs_soc.c

Modified: head/sys/dev/mvs/mvs.h
==============================================================================
--- head/sys/dev/mvs/mvs.h	Wed Feb  1 13:33:53 2012	(r230864)
+++ head/sys/dev/mvs/mvs.h	Wed Feb  1 13:39:52 2012	(r230865)
@@ -61,6 +61,9 @@
 
 #define CHIP_SOC_LED		0x2C	/* SoC LED Configuration */
 
+/* Additional mask for SoC devices with less than 4 channels */
+#define CHIP_SOC_HC0_MASK(num)	(0xff >> ((4 - (num)) * 2))
+
 /* Chip CCC registers */
 #define CHIP_ICC		0x18008
 #define CHIP_ICC_ALL_PORTS	 (1 << 4)	/* all ports irq event */

Modified: head/sys/dev/mvs/mvs_soc.c
==============================================================================
--- head/sys/dev/mvs/mvs_soc.c	Wed Feb  1 13:33:53 2012	(r230864)
+++ head/sys/dev/mvs/mvs_soc.c	Wed Feb  1 13:39:52 2012	(r230865)
@@ -216,7 +216,9 @@ mvs_ctlr_setup(device_t dev)
 	if (ccc)
 		ccim |= IC_HC0_COAL_DONE;
 	/* Enable chip interrupts */
-	ctlr->gmim = (ccc ? IC_HC0_COAL_DONE : IC_DONE_HC0) | IC_ERR_HC0;
+	ctlr->gmim = ((ccc ? IC_HC0_COAL_DONE :
+	    (IC_DONE_HC0 & CHIP_SOC_HC0_MASK(ctlr->channels))) |
+	    (IC_ERR_HC0 & CHIP_SOC_HC0_MASK(ctlr->channels)));
 	ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim);
 	return (0);
 }
@@ -291,25 +293,26 @@ mvs_intr(void *data)
 	struct mvs_controller *ctlr = data;
 	struct mvs_intr_arg arg;
 	void (*function)(void *);
-	int p;
+	int p, chan_num;
 	u_int32_t ic, aic;
 
 	ic = ATA_INL(ctlr->r_mem, CHIP_SOC_MIC);
 	if ((ic & IC_HC0) == 0)
 		return;
+
 	/* Acknowledge interrupts of this HC. */
 	aic = 0;
-	if (ic & (IC_DONE_IRQ << 0))
-		aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
-	if (ic & (IC_DONE_IRQ << 2))
-		aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
-	if (ic & (IC_DONE_IRQ << 4))
-		aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
-	if (ic & (IC_DONE_IRQ << 6))
-		aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
+
+	/* Processing interrupts from each initialized channel */
+	for (chan_num = 0; chan_num < ctlr->channels; chan_num++) {
+		if (ic & (IC_DONE_IRQ << (chan_num * 2)))
+			aic |= HC_IC_DONE(chan_num) | HC_IC_DEV(chan_num);
+	}
+
 	if (ic & IC_HC0_COAL_DONE)
 		aic |= HC_IC_COAL;
 	ATA_OUTL(ctlr->r_mem, HC_IC, ~aic);
+
 	/* Call per-port interrupt handler. */
 	for (p = 0; p < ctlr->channels; p++) {
 		arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202011339.q11DdrRY089245>