summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/ata-all.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ata/ata-all.c')
-rw-r--r--sys/dev/ata/ata-all.c70
1 files changed, 53 insertions, 17 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 17f3dc3..e66a4ac 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -87,10 +87,10 @@ static u_int8_t ata_drawersensor(struct ata_device *, int, u_int8_t, u_int8_t);
SYSCTL_NODE(_hw, OID_AUTO, ata, CTLFLAG_RD, 0, "ATA driver parameters");
/* global vars */
+struct intr_config_hook *ata_delayed_attach = NULL;
devclass_t ata_devclass;
/* local vars */
-static struct intr_config_hook *ata_delayed_attach = NULL;
static MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
/* misc defines */
@@ -134,7 +134,9 @@ ata_probe(device_t dev)
(int)rman_get_start(ch->r_altio),
(ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0);
+ ch->lock_func(ch, ATA_LF_LOCK);
ata_reset(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
ch->device[MASTER].channel = ch;
ch->device[MASTER].unit = ATA_MASTER;
@@ -186,6 +188,7 @@ ata_attach(device_t dev)
* otherwise attach what the probe has found in ch->devices.
*/
if (!ata_delayed_attach) {
+ ch->lock_func(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_SLAVE)
if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
ch->devices &= ~ATA_ATA_SLAVE;
@@ -213,6 +216,7 @@ ata_attach(device_t dev)
#ifdef DEV_ATAPICAM
atapi_cam_attach_bus(ch);
#endif
+ ch->lock_func(ch, ATA_LF_UNLOCK);
}
return 0;
}
@@ -228,6 +232,7 @@ ata_detach(device_t dev)
return ENXIO;
/* make sure channel is not busy */
+ ch->lock_func(ch, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(ch, ATA_CONTROL);
s = splbio();
@@ -274,13 +279,23 @@ ata_detach(device_t dev)
ch->r_bmio = NULL;
ch->r_irq = NULL;
ATA_UNLOCK_CH(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
return 0;
}
int
ata_resume(device_t dev)
{
- return ata_reinit(device_get_softc(dev));
+ struct ata_channel *ch;
+ int error;
+
+ if (!dev || !(ch = device_get_softc(dev)))
+ return ENXIO;
+
+ ch->lock_func(ch, ATA_LF_LOCK);
+ error = ata_reinit(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
+ return error;
}
static int
@@ -313,9 +328,10 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
case ATAREINIT:
if (!device || !(ch = device_get_softc(device)))
return ENXIO;
+ ch->lock_func(ch, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
- if ((error = ata_reinit(ch)))
- ATA_UNLOCK_CH(ch);
+ error = ata_reinit(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
return error;
case ATAGMODE:
@@ -339,6 +355,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
if (!device || !(ch = device_get_softc(device)))
return ENXIO;
+ ch->lock_func(ch, ATA_LF_LOCK);
if ((iocmd->device == MASTER || iocmd->device == -1) &&
iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) {
ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]);
@@ -354,6 +371,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
}
else
iocmd->u.mode.mode[SLAVE] = -1;
+ ch->lock_func(ch, ATA_LF_UNLOCK);
return 0;
case ATAGPARM:
@@ -386,6 +404,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
if (!device || !(ch = device_get_softc(device)))
return ENXIO;
+ ch->lock_func(ch, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
if (iocmd->device == SLAVE)
@@ -399,6 +418,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
id2 = ata_drawersensor(atadev, 0, 0x4f, 0);
if (id1 != 0xa3 || id2 != 0x5c) {
ATA_UNLOCK_CH(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
return ENXIO;
}
@@ -419,6 +439,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
iocmd->u.enclosure.v12 = ata_drawersensor(atadev, 0, 0x24, 0) * 61;
ATA_UNLOCK_CH(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
return 0;
}
@@ -533,12 +554,6 @@ ata_boot_attach(void)
struct ata_channel *ch;
int ctlr;
- if (ata_delayed_attach) {
- config_intrhook_disestablish(ata_delayed_attach);
- free(ata_delayed_attach, M_TEMP);
- ata_delayed_attach = NULL;
- }
-
/*
* run through all ata devices and look for real ATA & ATAPI devices
* using the hints we found in the early probe, this avoids some of
@@ -547,6 +562,7 @@ ata_boot_attach(void)
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
+ ch->lock_func(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_SLAVE)
if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
ch->devices &= ~ATA_ATA_SLAVE;
@@ -559,24 +575,26 @@ ata_boot_attach(void)
if (ch->devices & ATA_ATAPI_MASTER)
if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
ch->devices &= ~ATA_ATAPI_MASTER;
+ ch->lock_func(ch, ATA_LF_UNLOCK);
}
-
#ifdef DEV_ATADISK
/* now we know whats there, do the real attach, first the ATA disks */
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
+ ch->lock_func(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_MASTER)
ad_attach(&ch->device[MASTER]);
if (ch->devices & ATA_ATA_SLAVE)
ad_attach(&ch->device[SLAVE]);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
}
- ata_raid_attach();
#endif
/* then the atapi devices */
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
+ ch->lock_func(ch, ATA_LF_LOCK);
#if DEV_ATAPIALL
if (ch->devices & ATA_ATAPI_MASTER)
atapi_attach(&ch->device[MASTER]);
@@ -586,7 +604,14 @@ ata_boot_attach(void)
#ifdef DEV_ATAPICAM
atapi_cam_attach_bus(ch);
#endif
+ ch->lock_func(ch, ATA_LF_UNLOCK);
}
+ if (ata_delayed_attach) {
+ config_intrhook_disestablish(ata_delayed_attach);
+ free(ata_delayed_attach, M_TEMP);
+ ata_delayed_attach = NULL;
+ }
+ ata_raid_attach();
}
static void
@@ -598,7 +623,7 @@ ata_intr(void *data)
* device or our twin ATA channel, so call ch->intr_func to figure
* out if it is really an interrupt we should process here
*/
- if (ch->intr_func && ch->intr_func(ch))
+ if (!ch->intr_func(ch))
return;
/* if drive is busy it didn't interrupt */
@@ -638,14 +663,20 @@ ata_intr(void *data)
return;
}
+ if (ch->active & ATA_WAIT_INTR) {
+ ATA_UNLOCK_CH(ch);
+ return;
+ }
+
if ((ch->flags & ATA_QUEUED) &&
ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_SERVICE) {
ATA_FORCELOCK_CH(ch, ATA_ACTIVE);
if (ata_service(ch) == ATA_OP_CONTINUES)
return;
}
- ATA_UNLOCK_CH(ch);
ch->running = NULL;
+ ATA_UNLOCK_CH(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
ata_start(ch);
return;
}
@@ -661,6 +692,7 @@ ata_start(struct ata_channel *ch)
#endif
int s;
+ ch->lock_func(ch, ATA_LF_LOCK);
if (!ATA_LOCK_CH(ch, ATA_ACTIVE))
return;
@@ -703,6 +735,7 @@ ata_start(struct ata_channel *ch)
}
#endif
ATA_UNLOCK_CH(ch);
+ ch->lock_func(ch, ATA_LF_UNLOCK);
splx(s);
}
@@ -841,10 +874,13 @@ ata_reinit(struct ata_channel *ch)
{
int devices, misdev, newdev;
- if (!ch->r_io || !ch->r_altio || !ch->r_irq)
+ ATA_FORCELOCK_CH(ch, ATA_CONTROL);
+
+ if (!ch->r_io || !ch->r_altio || !ch->r_irq) {
+ ATA_UNLOCK_CH(ch);
return ENXIO;
+ }
- ATA_FORCELOCK_CH(ch, ATA_CONTROL);
ch->running = NULL;
devices = ch->devices;
ata_printf(ch, -1, "resetting devices ..\n");
@@ -1263,7 +1299,7 @@ ata_change_mode(struct ata_device *atadev, int mode)
ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE);
ata_dmainit(atadev, pmode, wmode, umode);
ATA_UNLOCK_CH(atadev->channel);
- ata_start(atadev->channel); /* XXX SOS */
+ ata_start(atadev->channel);
}
int
OpenPOWER on IntegriCloud