summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/ata-all.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2002-12-03 20:20:44 +0000
committersos <sos@FreeBSD.org>2002-12-03 20:20:44 +0000
commit71edc5e4eb36ba021cec4018ead8d4e7bd6d759d (patch)
tree905ab8bf0e6cc6504398fed7db55f39319883169 /sys/dev/ata/ata-all.c
parent9a5da33a40507cd3fd2cebf1aa8999a6cdd27862 (diff)
downloadFreeBSD-src-71edc5e4eb36ba021cec4018ead8d4e7bd6d759d.zip
FreeBSD-src-71edc5e4eb36ba021cec4018ead8d4e7bd6d759d.tar.gz
Add support for the PC98 platform to the ATA driver.
This mostly consists of functionality to serialize accesses to the two ATA channels (which can also be used to "fix" certain PCI based controllers). Add support for Acard controllers. Enable the ATA driver in PC98 GENERIC, and add device hints. Update man page with latest support. The PC98 core team has kindly provided me with a PC98 machine that made this all possible, thanks to all that contributed to that effort, without that this would probably newer have been possible.. Approved by: re@
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