summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2005-12-30 23:15:02 +0000
committersos <sos@FreeBSD.org>2005-12-30 23:15:02 +0000
commit1a1e1570e1ec769808ffd99e879b7ac9f5d05332 (patch)
tree85bf22064d4d94aa3f6b4554ac49dde177c4ade0 /sys
parent6c2bd225d811776bd43873214e9391603bcd3d16 (diff)
downloadFreeBSD-src-1a1e1570e1ec769808ffd99e879b7ac9f5d05332.zip
FreeBSD-src-1a1e1570e1ec769808ffd99e879b7ac9f5d05332.tar.gz
Add hotplug support for Marvell chips.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ata/ata-chipset.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index 5a4e214..b8121b0 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -2275,35 +2275,62 @@ ata_marvell_intr(void *data)
struct ata_channel *ch;
struct ata_request *request;
struct ata_marvell_response *response;
- u_int32_t cause, icr0 = 0, icr1 = 0;
+ u_int32_t cause, icr = 0;
int unit;
+ /* get main interrupt cause register contents to save time below */
cause = ATA_INL(ctlr->r_res1, 0x01d60);
- if ((icr0 = ATA_INL(ctlr->r_res1, 0x20014)))
- ATA_OUTL(ctlr->r_res1, 0x20014, ~icr0);
- if (ctlr->channels > 4) {
- if ((icr1 = ATA_INL(ctlr->r_res1, 0x30014)))
- ATA_OUTL(ctlr->r_res1, 0x30014, ~icr1);
- }
for (unit = 0; unit < ctlr->channels; unit++) {
- u_int32_t icr;
- int shift;
+ int shift = (unit << 1) + (unit >= 4);
if (!(ch = ctlr->interrupt[unit].argument))
continue;
mtx_lock(&ch->state_mtx);
- shift = unit << 1;
- if (ch->unit < 4)
- icr = icr0;
- else {
- icr = icr1;
- shift++;
+ if (unit == 0) {
+ icr = ATA_INL(ctlr->r_res1, 0x20014);
+ ATA_OUTL(ctlr->r_res1, 0x20014, ~icr);
+ }
+ if (unit == 4) {
+ icr = ATA_INL(ctlr->r_res1, 0x30014);
+ ATA_OUTL(ctlr->r_res1, 0x30014, ~icr);
}
/* do we have any errors flagged ? */
if (cause & (1 << shift)) {
+ struct ata_connect_task *tp;
+ u_int32_t error =
+ ATA_INL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch));
+
+ /* check for and handle disconnect events */
+ if ((error & 0x00000008) &&
+ (tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+
+ if (bootverbose)
+ device_printf(ch->dev, "DISCONNECT requested\n");
+ tp->action = ATA_C_DETACH;
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
+ }
+
+ /* check for and handle connect events */
+ if ((error & 0x00000010) &&
+ (tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+
+ if (bootverbose)
+ device_printf(ch->dev, "CONNECT requested\n");
+ tp->action = ATA_C_ATTACH;
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
+ }
+
/* clear SATA error register */
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
OpenPOWER on IntegriCloud