summaryrefslogtreecommitdiffstats
path: root/sys/dev/mvs
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2012-02-01 13:39:52 +0000
committerraj <raj@FreeBSD.org>2012-02-01 13:39:52 +0000
commitb1a5cbc2ba8071ddbaa46c70fce5a49f98b8583d (patch)
tree792af0f236047d8086c9ee162a3e9e47565e5d3d /sys/dev/mvs
parentc5ba0185aafb67b6994767023cdb5c5a1a0960f6 (diff)
downloadFreeBSD-src-b1a5cbc2ba8071ddbaa46c70fce5a49f98b8583d.zip
FreeBSD-src-b1a5cbc2ba8071ddbaa46c70fce5a49f98b8583d.tar.gz
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
Diffstat (limited to 'sys/dev/mvs')
-rw-r--r--sys/dev/mvs/mvs.h3
-rw-r--r--sys/dev/mvs/mvs_soc.c23
2 files changed, 16 insertions, 10 deletions
diff --git a/sys/dev/mvs/mvs.h b/sys/dev/mvs/mvs.h
index 3fe106a..f4e4a61 100644
--- a/sys/dev/mvs/mvs.h
+++ b/sys/dev/mvs/mvs.h
@@ -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 */
diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c
index 9c5c479..19fe51f 100644
--- a/sys/dev/mvs/mvs_soc.c
+++ b/sys/dev/mvs/mvs_soc.c
@@ -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);
OpenPOWER on IntegriCloud