diff options
author | sos <sos@FreeBSD.org> | 2005-12-30 23:15:02 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2005-12-30 23:15:02 +0000 |
commit | 1a1e1570e1ec769808ffd99e879b7ac9f5d05332 (patch) | |
tree | 85bf22064d4d94aa3f6b4554ac49dde177c4ade0 /sys | |
parent | 6c2bd225d811776bd43873214e9391603bcd3d16 (diff) | |
download | FreeBSD-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.c | 57 |
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)); |