diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c index 51da83aef10a..2866f0134fd8 100644 --- a/sys/dev/ata/ata.c +++ b/sys/dev/ata/ata.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.94 2008/01/04 21:17:50 ad Exp $ */ +/* $NetBSD: ata.c,v 1.95 2008/01/10 07:41:20 dyoung Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.94 2008/01/04 21:17:50 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.95 2008/01/10 07:41:20 dyoung Exp $"); #include "opt_ata.h" @@ -107,6 +107,7 @@ const struct cdevsw atabus_cdevsw = { extern struct cfdriver atabus_cd; +static void atabus_childdetached(device_t, device_t); static bool atabus_resume(device_t); static bool atabus_suspend(device_t); @@ -218,7 +219,7 @@ atabusconfig(struct atabus_softc *atabus_sc) * Fake the autoconfig "not configured" message */ aprint_normal("atapibus at %s not configured\n", - atac->atac_dev.dv_xname); + device_xname(&atac->atac_dev)); chp->atapibus = NULL; s = splbio(); for (i = 0; i < chp->ch_ndrive; i++) @@ -373,7 +374,7 @@ atabus_thread(void *arg) * Autoconfiguration match routine. */ static int -atabus_match(struct device *parent, struct cfdata *cf, void *aux) +atabus_match(device_t parent, struct cfdata *cf, void *aux) { struct ata_channel *chp = aux; @@ -393,9 +394,9 @@ atabus_match(struct device *parent, struct cfdata *cf, void *aux) * Autoconfiguration attach routine. */ static void -atabus_attach(struct device *parent, struct device *self, void *aux) +atabus_attach(device_t parent, device_t self, void *aux) { - struct atabus_softc *sc = (void *) self; + struct atabus_softc *sc = device_private(self); struct ata_channel *chp = aux; struct atabus_initq *initq; int error; @@ -414,9 +415,9 @@ atabus_attach(struct device *parent, struct device *self, void *aux) config_pending_incr(); if ((error = kthread_create(PRI_NONE, 0, NULL, atabus_thread, sc, - &chp->ch_thread, "%s", sc->sc_dev.dv_xname)) != 0) - aprint_error("%s: unable to create kernel thread: error %d\n", - sc->sc_dev.dv_xname, error); + &chp->ch_thread, "%s", device_xname(self))) != 0) + aprint_error_dev(self, + "unable to create kernel thread: error %d\n", error); if (!pmf_device_register(self, atabus_suspend, atabus_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); @@ -428,11 +429,11 @@ atabus_attach(struct device *parent, struct device *self, void *aux) * Autoconfiguration activation routine. */ static int -atabus_activate(struct device *self, enum devact act) +atabus_activate(device_t self, enum devact act) { - struct atabus_softc *sc = (void *) self; + struct atabus_softc *sc = device_private(self); struct ata_channel *chp = sc->sc_chan; - struct device *dev = NULL; + device_t dev = NULL; int s, i, error = 0; s = splbio(); @@ -457,8 +458,8 @@ atabus_activate(struct device *self, enum devact act) for (i = 0; i < chp->ch_ndrive; i++) { if ((dev = chp->ch_drive[i].drv_softc) != NULL) { ATADEBUG_PRINT(("atabus_activate: %s: " - "deactivating %s\n", sc->sc_dev.dv_xname, - dev->dv_xname), + "deactivating %s\n", device_xname(self), + device_xname(dev)), DEBUG_DETACH); error = config_deactivate(dev); if (error) @@ -473,8 +474,8 @@ atabus_activate(struct device *self, enum devact act) #ifdef ATADEBUG if (dev != NULL && error != 0) ATADEBUG_PRINT(("atabus_activate: %s: " - "error %d deactivating %s\n", sc->sc_dev.dv_xname, - error, dev->dv_xname), DEBUG_DETACH); + "error %d deactivating %s\n", device_xname(self), + error, device_xname(dev)), DEBUG_DETACH); #endif /* ATADEBUG */ return (error); @@ -486,61 +487,108 @@ atabus_activate(struct device *self, enum devact act) * Autoconfiguration detach routine. */ static int -atabus_detach(struct device *self, int flags) +atabus_detach(device_t self, int flags) { - struct atabus_softc *sc = (void *) self; + struct atabus_softc *sc = device_private(self); struct ata_channel *chp = sc->sc_chan; - struct device *dev = NULL; + device_t dev = NULL; int s, i, error = 0; + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); + /* Shutdown the channel. */ s = splbio(); /* XXX ALSO NEED AN INTERLOCK HERE. */ chp->ch_flags |= ATACH_SHUTDOWN; splx(s); + + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); wakeup(&chp->ch_thread); + + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); while (chp->ch_thread != NULL) (void) tsleep(&chp->ch_flags, PRIBIO, "atadown", 0); + + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); /* * Detach atapibus and its children. */ if ((dev = chp->atapibus) != NULL) { ATADEBUG_PRINT(("atabus_detach: %s: detaching %s\n", - sc->sc_dev.dv_xname, dev->dv_xname), DEBUG_DETACH); + device_xname(self), device_xname(dev)), DEBUG_DETACH); + + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); error = config_detach(dev, flags); if (error) goto out; } + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); + /* + * Detach our other children. + */ + for (i = 0; i < chp->ch_ndrive; i++) { + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); + if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) + continue; + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); + if ((dev = chp->ch_drive[i].drv_softc) != NULL) { + ATADEBUG_PRINT(("atabus_detach: %s: detaching %s\n", + device_xname(self), device_xname(dev)), + DEBUG_DETACH); + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); + error = config_detach(dev, flags); + if (error) + goto out; + } + } + + out: + aprint_error_dev(self, "%s.%d\n", __func__, __LINE__); +#ifdef ATADEBUG + if (dev != NULL && error != 0) + ATADEBUG_PRINT(("atabus_detach: %s: error %d detaching %s\n", + device_xname(self), error, device_xname(dev)), + DEBUG_DETACH); +#endif /* ATADEBUG */ + + return (error); +} + +void +atabus_childdetached(device_t self, device_t child) +{ + struct atabus_softc *sc = device_private(self); + struct ata_channel *chp = sc->sc_chan; + int i; + + /* + * atapibus detached. + */ + if (child == chp->atapibus) { + chp->atapibus = NULL; + return; + } + /* * Detach our other children. */ for (i = 0; i < chp->ch_ndrive; i++) { if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) continue; - if ((dev = chp->ch_drive[i].drv_softc) != NULL) { - ATADEBUG_PRINT(("atabus_detach: %s: detaching %s\n", - sc->sc_dev.dv_xname, dev->dv_xname), - DEBUG_DETACH); - error = config_detach(dev, flags); - if (error) - goto out; + if (child == chp->ch_drive[i].drv_softc) { + chp->ch_drive[i].drv_softc = NULL; + chp->ch_drive[i].drive_flags = 0; + return; } } - out: -#ifdef ATADEBUG - if (dev != NULL && error != 0) - ATADEBUG_PRINT(("atabus_detach: %s: error %d detaching %s\n", - sc->sc_dev.dv_xname, error, dev->dv_xname), - DEBUG_DETACH); -#endif /* ATADEBUG */ - - return (error); + aprint_error_dev(self, "unknown child %p", (const void *)child); } -CFATTACH_DECL(atabus, sizeof(struct atabus_softc), - atabus_match, atabus_attach, atabus_detach, atabus_activate); +CFATTACH_DECL2(atabus, sizeof(struct atabus_softc), + atabus_match, atabus_attach, atabus_detach, atabus_activate, NULL, + atabus_childdetached); /***************************************************************************** * Common ATA bus operations. @@ -1015,8 +1063,8 @@ ata_print_modes(struct ata_channel *chp) if ((drvp->drive_flags & DRIVE) == 0 || drvp->drv_softc == NULL) continue; aprint_verbose("%s(%s:%d:%d): using PIO mode %d", - drvp->drv_softc->dv_xname, - atac->atac_dev.dv_xname, + device_xname(drvp->drv_softc), + device_xname(&atac->atac_dev), chp->ch_channel, drvp->drive, drvp->PIO_mode); #if NATA_DMA if (drvp->drive_flags & DRIVE_DMA) @@ -1063,7 +1111,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags) { struct ata_channel *chp = drvp->chnl_softc; struct atac_softc *atac = chp->ch_atac; - struct device *drv_dev = drvp->drv_softc; + device_t drv_dev = drvp->drv_softc; int cf_flags = device_cfdata(drv_dev)->cf_flags; /* if drive or controller don't know its mode, we can't do much */ @@ -1083,7 +1131,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags) if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) { drvp->UDMA_mode--; printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n", - drv_dev->dv_xname, drvp->UDMA_mode); + device_xname(drv_dev), drvp->UDMA_mode); } #endif @@ -1094,7 +1142,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags) drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA); drvp->PIO_mode = drvp->PIO_cap; printf("%s: transfer error, downgrading to PIO mode %d\n", - drv_dev->dv_xname, drvp->PIO_mode); + device_xname(drv_dev), drvp->PIO_mode); } else /* already using PIO, can't downgrade */ return 0; @@ -1116,7 +1164,7 @@ ata_probe_caps(struct ata_drive_datas *drvp) struct ataparams params, params2; struct ata_channel *chp = drvp->chnl_softc; struct atac_softc *atac = chp->ch_atac; - struct device *drv_dev = drvp->drv_softc; + device_t drv_dev = drvp->drv_softc; int i, printed, s; const char *sep = ""; int cf_flags; @@ -1143,7 +1191,7 @@ ata_probe_caps(struct ata_drive_datas *drvp) splx(s); } else { aprint_verbose("%s: 32-bit data port\n", - drv_dev->dv_xname); + device_xname(drv_dev)); } } #if 0 /* Some ultra-DMA drives claims to only support ATA-3. sigh */ @@ -1152,7 +1200,7 @@ ata_probe_caps(struct ata_drive_datas *drvp) for (i = 14; i > 0; i--) { if (params.atap_ata_major & (1 << i)) { aprint_verbose("%s: ATA version %d\n", - drv_dev->dv_xname, i); + device_xname(drv_dev), i); drvp->ata_vers = i; break; } @@ -1198,7 +1246,7 @@ ata_probe_caps(struct ata_drive_datas *drvp) continue; if (!printed) { aprint_verbose("%s: drive supports PIO mode %d", - drv_dev->dv_xname, i + 3); + device_xname(drv_dev), i + 3); sep = ","; printed = 1; } @@ -1468,7 +1516,7 @@ atabusioctl(dev_t dev, u_long cmd, void *addr, int flag, chp->ch_drive[drive].drv_softc, 0); if (error) return (error); - chp->ch_drive[drive].drv_softc = NULL; + KASSERT(chp->ch_drive[drive].drv_softc == NULL); } } error = 0;