summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/fdc.c
diff options
context:
space:
mode:
authorGarrett D'Amore <gdamore@opensolaris.org>2008-12-03 08:45:18 -0800
committerGarrett D'Amore <gdamore@opensolaris.org>2008-12-03 08:45:18 -0800
commitca925f54ccacc64abb1dc147c736397a9ccaab0e (patch)
treec7701a405d8348d5f0eb97ecd1886520581eac8f /usr/src/uts/common/io/fdc.c
parentce6768582b30bd39ea744f401db704f4e7753468 (diff)
downloadillumos-gate-ca925f54ccacc64abb1dc147c736397a9ccaab0e.tar.gz
6615472 The fd driver needs to support DDI_SUSPEND/DDI_RESUME
Diffstat (limited to 'usr/src/uts/common/io/fdc.c')
-rw-r--r--usr/src/uts/common/io/fdc.c160
1 files changed, 76 insertions, 84 deletions
diff --git a/usr/src/uts/common/io/fdc.c b/usr/src/uts/common/io/fdc.c
index 8e87ca856f..444b6b46e5 100644
--- a/usr/src/uts/common/io/fdc.c
+++ b/usr/src/uts/common/io/fdc.c
@@ -53,6 +53,7 @@
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/cmn_err.h>
+#include <sys/note.h>
#include <sys/debug.h>
#include <sys/kmem.h>
#include <sys/stat.h>
@@ -296,10 +297,7 @@ _info(struct modinfo *modinfop)
}
-int fdc_start(struct fcu_obj *);
int fdc_abort(struct fcu_obj *);
-int fdc_getcap(struct fcu_obj *, char *, int);
-int fdc_setcap(struct fcu_obj *, char *, int, int);
int fdc_dkinfo(struct fcu_obj *, struct dk_cinfo *);
int fdc_select(struct fcu_obj *, int, int);
int fdgetchng(struct fcu_obj *, int);
@@ -310,10 +308,7 @@ int fdtrkformat(struct fcu_obj *, int, int, int, int);
int fdrawioctl(struct fcu_obj *, int, caddr_t);
static struct fcobjops fdc_iops = {
- fdc_start, /* controller start */
fdc_abort, /* controller abort */
- fdc_getcap, /* capability retrieval */
- fdc_setcap, /* capability establishment */
fdc_dkinfo, /* get disk controller info */
fdc_select, /* select / deselect unit */
@@ -333,7 +328,7 @@ static struct fcobjops fdc_iops = {
void encode(xlate_tbl_t *tablep, int val, uchar_t *rcode);
int decode(xlate_tbl_t *, int, int *);
static int fdc_propinit1(struct fdcntlr *, int);
-static void fdc_propinit2(struct fdcntlr *, int);
+static void fdc_propinit2(struct fdcntlr *);
void fdcquiesce(struct fdcntlr *);
int fdcsense_chng(struct fdcntlr *, int);
int fdcsense_drv(struct fdcntlr *, int);
@@ -352,7 +347,6 @@ int fdc_docmd(struct fdcntlr *, uchar_t *, uchar_t);
int fdc_result(struct fdcntlr *, uchar_t *, uchar_t);
-/* ARGSUSED */
static int
fdc_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
void *arg, void *result)
@@ -360,6 +354,8 @@ fdc_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
struct fdcntlr *fcp;
struct fcu_obj *fjp;
+ _NOTE(ARGUNUSED(result));
+
FCERRPRINT(FDEP_L0, FDEM_ATTA,
(CE_CONT, "fdc_bus_ctl: cmd= %x\n", ctlop));
@@ -429,13 +425,14 @@ fdc_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
}
}
-/* ARGSUSED */
static int
fdc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
{
struct fdcntlr *fcp;
int rval;
+ _NOTE(ARGUNUSED(dip));
+
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
if (fcp = ddi_get_soft_state(fdc_state_head, (dev_t)arg)) {
@@ -486,7 +483,6 @@ fdc_probe(dev_info_t *dip)
return (DDI_PROBE_SUCCESS);
}
-/* ARGSUSED */
static int
fdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
@@ -545,7 +541,7 @@ fdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
if (ddi_add_intr(dip, (uint_t)0, NULL,
(ddi_idevice_cookie_t *)0, fdc_intr, (caddr_t)fcp) !=
DDI_SUCCESS) {
- cmn_err(CE_WARN, "fdc: cannot add intr\n");
+ cmn_err(CE_WARN, "fdc: cannot add intr");
goto no_attach;
}
intr_set++;
@@ -557,7 +553,7 @@ fdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
*/
if (ddi_dmae_alloc(dip, fcp->c_dmachan, DDI_DMA_DONTWAIT, NULL)
!= DDI_SUCCESS) {
- cmn_err(CE_WARN, "fdc: cannot acquire dma%d\n",
+ cmn_err(CE_WARN, "fdc: cannot acquire dma%d",
fcp->c_dmachan);
goto no_attach;
}
@@ -596,12 +592,29 @@ fdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
mutex_exit(&fcp->c_lock);
sema_v(&fcp->c_selsem);
- fdc_propinit2(fcp, cntlr_num);
+ fdc_propinit2(fcp);
ddi_report_dev(dip);
return (DDI_SUCCESS);
case DDI_RESUME:
+
+ fcp = ddi_get_driver_private(dip);
+
+ mutex_enter(&fcp->c_lock);
+ fcp->c_suspended = B_FALSE;
+ fcp->c_csb.csb_xstate = FXS_RESET;
+ fcp->c_flags |= FCFLG_WAITING;
+ fdcquiesce(fcp);
+
+ while (fcp->c_flags & FCFLG_WAITING) {
+ cv_wait(&fcp->c_iocv, &fcp->c_lock);
+ }
+ mutex_exit(&fcp->c_lock);
+
+ /* should be good to go now */
+ sema_v(&fcp->c_selsem);
+
return (DDI_SUCCESS);
/* break; */
@@ -646,9 +659,8 @@ fdc_propinit1(struct fdcntlr *fcp, int cntlr)
return (DDI_SUCCESS);
}
-/* ARGSUSED */
static void
-fdc_propinit2(struct fdcntlr *fcp, int cntlr)
+fdc_propinit2(struct fdcntlr *fcp)
{
dev_info_t *dip;
int ccr;
@@ -724,7 +736,6 @@ fdc_propinit2(struct fdcntlr *fcp, int cntlr)
outb(fcp->c_regbase + FCR_CCR, 0);
}
-/* ARGSUSED */
static int
fdc_enhance_probe(struct fdcntlr *fcp)
{
@@ -826,12 +837,10 @@ fdc_enhance_probe(struct fdcntlr *fcp)
return (retcode);
}
-/* ARGSUSED */
static int
fdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
struct fdcntlr *fcp;
- struct fcu_obj *fjp;
int unit;
int rval = 0;
@@ -853,7 +862,7 @@ fdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
if (ddi_dmae_release(fcp->c_dip, fcp->c_dmachan) !=
DDI_SUCCESS)
cmn_err(CE_WARN, "fdc_detach: dma release failed, "
- "dip %p, dmachan %x\n",
+ "dip %p, dmachan %x",
(void*)fcp->c_dip, fcp->c_dmachan);
ddi_prop_remove_all(fcp->c_dip);
ddi_set_driver_private(fcp->c_dip, NULL);
@@ -867,28 +876,28 @@ fdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
case DDI_SUSPEND:
/*
- * Following code causes the fdc (floppy controller)
- * to suspend as long as there are no floppy drives
- * attached to it.
- * At present the floppy driver does not support
- * SUSPEND/RESUME.
- *
- * Check if any FD units are attached
+ * For suspend, we just use the semaphore to
+ * keep any child devices from accessing any of our
+ * hardware routines, and then shutdown the hardware.
*
- * For now, SUSPEND/RESUME is not supported
- * if a floppy drive is present.
- * So if any FD unit is attached return DDI_FAILURE
+ * On resume, we'll reinit the hardware and release the
+ * semaphore.
*/
- for (unit = 0; unit < NFDUN; unit++) {
- fjp = fcp->c_unit[unit];
- if (fjp->fj_flags & FUNIT_DRVATCH) {
- cmn_err(CE_WARN,
- "fdc_detach: fd attached, failing SUSPEND");
- return (DDI_FAILURE);
- }
+ sema_p(&fcp->c_selsem);
+
+ if (ddi_dmae_disable(fcp->c_dip, fcp->c_dmachan) !=
+ DDI_SUCCESS) {
+ cmn_err(CE_WARN, "fdc_suspend: dma disable failed, "
+ "dip %p, dmachan %x", (void *)fcp->c_dip,
+ fcp->c_dmachan);
+ /* give it back on failure */
+ sema_v(&fcp->c_selsem);
+ return (DDI_FAILURE);
}
- cmn_err(CE_NOTE, "fdc_detach: SUSPEND fdc");
+ mutex_enter(&fcp->c_lock);
+ fcp->c_suspended = B_TRUE;
+ mutex_exit(&fcp->c_lock);
rval = DDI_SUCCESS;
break;
@@ -901,13 +910,6 @@ fdc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
}
-/* ARGSUSED */
-int
-fdc_start(struct fcu_obj *fjp)
-{
- return (ENOSYS);
-}
-
int
fdc_abort(struct fcu_obj *fjp)
{
@@ -928,7 +930,7 @@ fdc_abort(struct fcu_obj *fjp)
DDI_SUCCESS)
cmn_err(CE_WARN,
"fdc_detach: dma release failed, "
- "dip %p, dmachan %x\n",
+ "dip %p, dmachan %x",
(void*)fcp->c_dip, fcp->c_dmachan);
}
mutex_exit(&fcp->c_lock);
@@ -938,20 +940,6 @@ fdc_abort(struct fcu_obj *fjp)
return (DDI_FAILURE);
}
-/* ARGSUSED */
-int
-fdc_getcap(struct fcu_obj *fjp, char *a, int i)
-{
- return (ENOSYS);
-}
-
-/* ARGSUSED */
-int
-fdc_setcap(struct fcu_obj *fjp, char *a, int i, int j)
-{
- return (ENOSYS);
-}
-
int
fdc_dkinfo(struct fcu_obj *fjp, struct dk_cinfo *dcp)
{
@@ -975,7 +963,6 @@ fdc_dkinfo(struct fcu_obj *fjp, struct dk_cinfo *dcp)
/*
* on=> non-zero = select, 0 = de-select
*/
-/* ARGSUSED */
int
fdc_select(struct fcu_obj *fjp, int funit, int on)
{
@@ -997,7 +984,7 @@ fdc_select(struct fcu_obj *fjp, int funit, int on)
cmn_err(CE_WARN,
"fdc_select: controller setup rejected "
"fdcntrl %p transfer rate %x step rate %x"
- " head load time 40\n", (void*)fcp,
+ " head load time 40", (void*)fcp,
fjp->fj_chars->fdc_transfer_rate,
fjp->fj_drive->fdd_steprate);
}
@@ -1054,7 +1041,7 @@ int
fdgetchng(struct fcu_obj *fjp, int funit)
{
if (fdcsense_drv(fjp->fj_fdc, funit & 3))
- cmn_err(CE_WARN, "fdgetchng: write protect check failed\n");
+ cmn_err(CE_WARN, "fdgetchng: write protect check failed");
return (fdcsense_chng(fjp->fj_fdc, funit & 3));
}
@@ -1123,7 +1110,7 @@ fdrecalseek(struct fcu_obj *fjp, int funit, int arg, int execflg)
rval = ENODEV;
if (fdcsense_drv(fcp, unit))
- cmn_err(CE_WARN, "fdgetchng: write protect check failed\n");
+ cmn_err(CE_WARN, "fdgetchng: write protect check failed");
out:
return (rval);
}
@@ -1217,13 +1204,13 @@ fdrw(struct fcu_obj *fjp, int funit, int rw, int cyl, int head,
csb->csb_handle_bound = 1;
if (ddi_dma_numwin(csb->csb_dmahandle, &csb->csb_dmawincnt) !=
DDI_SUCCESS) {
- cmn_err(CE_WARN, "fdrw: dma numwin failed\n");
+ cmn_err(CE_WARN, "fdrw: dma numwin failed");
rval = EINVAL;
goto out;
}
} else {
cmn_err(CE_WARN,
- "fdrw: dma addr bind handle failed, rval = %d\n", rval);
+ "fdrw: dma addr bind handle failed, rval = %d", rval);
rval = EINVAL;
goto out;
}
@@ -1239,7 +1226,7 @@ out:
if (ddi_dma_unbind_handle(csb->csb_dmahandle) !=
DDI_SUCCESS)
cmn_err(CE_WARN, "fdrw: "
- "dma unbind handle failed\n");
+ "dma unbind handle failed");
csb->csb_handle_bound = 0;
}
if (mem_handle != NULL) {
@@ -1345,13 +1332,13 @@ fdtrkformat(struct fcu_obj *fjp, int funit, int cyl, int head, int filldata)
csb->csb_handle_bound = 1;
if (ddi_dma_numwin(csb->csb_dmahandle, &csb->csb_dmawincnt) !=
DDI_SUCCESS) {
- cmn_err(CE_WARN, "fdtrkformat: dma numwin failed\n");
+ cmn_err(CE_WARN, "fdtrkformat: dma numwin failed");
rval = EINVAL;
goto out;
}
} else {
cmn_err(CE_WARN,
- "fdtrkformat: dma buf bind handle failed, rval = %d\n",
+ "fdtrkformat: dma buf bind handle failed, rval = %d",
rval);
rval = EINVAL;
goto out;
@@ -1364,7 +1351,7 @@ out:
if (ddi_dma_unbind_handle(csb->csb_dmahandle) !=
DDI_SUCCESS)
cmn_err(CE_WARN, "fdtrkformat: "
- "dma unbind handle failed\n");
+ "dma unbind handle failed");
csb->csb_handle_bound = 0;
}
if (mem_handle != NULL) {
@@ -1376,7 +1363,6 @@ out:
return (rval);
}
-/* ARGSUSED */
int
fdrawioctl(struct fcu_obj *fjp, int funit, caddr_t arg)
{
@@ -1393,6 +1379,8 @@ fdrawioctl(struct fcu_obj *fjp, int funit, caddr_t arg)
caddr_t aligned_buf;
size_t real_size;
+ _NOTE(ARGUNUSED(funit));
+
FCERRPRINT(FDEP_L2, FDEM_RAWI,
(CE_NOTE, "fdrawioctl: cmd[0]=0x%x", fdrp->fdr_cmd[0]));
@@ -1509,13 +1497,13 @@ fdrawioctl(struct fcu_obj *fjp, int funit, caddr_t arg)
if (ddi_dma_numwin(csb->csb_dmahandle,
&csb->csb_dmawincnt) != DDI_SUCCESS) {
cmn_err(CE_WARN,
- "fdrawioctl: dma numwin failed\n");
+ "fdrawioctl: dma numwin failed");
rval = EINVAL;
goto out;
}
} else {
cmn_err(CE_WARN, "fdrawioctl: "
- "dma buf bind handle failed, rval = %d\n", rval);
+ "dma buf bind handle failed, rval = %d", rval);
rval = EINVAL;
goto out;
}
@@ -1565,7 +1553,7 @@ out:
if (ddi_dma_unbind_handle(csb->csb_dmahandle) !=
DDI_SUCCESS)
cmn_err(CE_WARN, "fdrawioctl: "
- "dma unbind handle failed\n");
+ "dma unbind handle failed");
csb->csb_handle_bound = 0;
}
if (mem_handle != NULL) {
@@ -1590,7 +1578,7 @@ encode(xlate_tbl_t *tablep, int val, uchar_t *rcode)
}
} while ((++tablep)->value);
*rcode = tablep->code;
- cmn_err(CE_WARN, "fdc encode failed, table %p val %x code %x\n",
+ cmn_err(CE_WARN, "fdc encode failed, table %p val %x code %x",
(void *)tablep, val, (uint_t)*rcode);
}
@@ -1685,7 +1673,7 @@ fdcquiesce(struct fdcntlr *fcp)
if (ddi_dmae_stop(fcp->c_dip, fcp->c_dmachan) != DDI_SUCCESS)
cmn_err(CE_WARN, "fdcquiesce: dmae stop failed, "
- "dip %p, dmachan %x\n",
+ "dip %p, dmachan %x",
(void*)fcp->c_dip, fcp->c_dmachan);
fcp->c_digout = (fcp->c_digout & (FD_DMTREN | FD_DRSEL)) | FD_ENABLE;
@@ -2054,7 +2042,7 @@ fdc_motorsm(struct fcu_obj *fjp, int input, int timeval)
(int)fjp->fj_unit, input, old_mstate));
#if 0
cmn_err(CE_WARN,
- "fdc_motorsm: unit %d bad input %d or bad state %d\n",
+ "fdc_motorsm: unit %d bad input %d or bad state %d",
(int)fjp->fj_unit, input, old_mstate);
fcp->c_mtrstate[unit] = FMS_OFF;
if (fcp->c_motort[unit] != 0) {
@@ -2143,7 +2131,7 @@ fdc_dmae_isr(struct fdcntlr *fcp)
return (&csb->csb_dmacookie);
}
} else
- cmn_err(CE_WARN, "fdc: unsolicited DMA interrupt\n");
+ cmn_err(CE_WARN, "fdc: unsolicited DMA interrupt");
return (NULL);
}
@@ -2216,7 +2204,7 @@ retry:
cmn_err(CE_WARN,
"fdc_select: controller setup rejected "
"fdcntrl %p transfer rate %x step rate %x "
- "head load time 40\n", (void*)fcp,
+ "head load time 40", (void*)fcp,
fjp->fj_chars->fdc_transfer_rate,
fjp->fj_drive->fdd_steprate);
@@ -2301,7 +2289,7 @@ retry:
if (ddi_dmae_prog(fcp->c_dip, &dmaereq, &csb->csb_dmacookie,
fcp->c_dmachan) != DDI_SUCCESS)
cmn_err(CE_WARN, "fdc_exec: dmae prog failed, "
- "dip %p, dmachan %x\n",
+ "dip %p, dmachan %x",
(void*)fcp->c_dip, fcp->c_dmachan);
}
@@ -2495,7 +2483,7 @@ fdrecover(struct fdcntlr *fcp)
&residual) != DDI_SUCCESS)
cmn_err(CE_WARN,
"fdc_recover: dmae getcnt failed, "
- "dip %p dmachan %x residual %x\n",
+ "dip %p dmachan %x residual %x",
(void*)fcp->c_dip, fcp->c_dmachan,
residual);
FCERRPRINT(FDEP_L2, FDEM_RECO,
@@ -2600,7 +2588,6 @@ fdrecover(struct fdcntlr *fcp)
/* Autovector Interrupt Entry Point */
-/* ARGSUSED */
static uint_t
fdc_intr(caddr_t arg)
{
@@ -2618,6 +2605,11 @@ fdc_intr(caddr_t arg)
csb = &fcp->c_csb;
mutex_enter(&fcp->c_lock);
+ if (fcp->c_suspended) {
+ mutex_exit(&fcp->c_lock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+
/*
* Wait for the RQM bit to be set, or until we've tested it
* a bunch of times (which may imply this isn't our interrupt).
@@ -2690,7 +2682,7 @@ fdc_intr(caddr_t arg)
DDI_SUCCESS) {
cmn_err(CE_WARN,
"fdc_intr: "
- "dma getwin failed\n");
+ "dma getwin failed");
}
csb->csb_dmacurrcookie = 0;
}
@@ -2700,7 +2692,7 @@ fdc_intr(caddr_t arg)
DDI_SUCCESS)
cmn_err(CE_WARN,
"fdc_intr: dmae prog failed, "
- "dip %p dmachannel %x\n",
+ "dip %p dmachannel %x",
(void*)fcp->c_dip,
fcp->c_dmachan);
@@ -2787,7 +2779,7 @@ fdwatch(void *arg)
if (fcp->c_flags & FCFLG_WAITING) {
if (ddi_dmae_stop(fcp->c_dip, fcp->c_dmachan) != DDI_SUCCESS)
cmn_err(CE_WARN, "fdwatch: dmae stop failed, "
- "dip %p, dmachan %x\n",
+ "dip %p, dmachan %x",
(void*)fcp->c_dip, fcp->c_dmachan);
csb = &fcp->c_csb;
FCERRPRINT(FDEP_L3, FDEM_WATC,