summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4/io/efcode
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun4/io/efcode')
-rw-r--r--usr/src/uts/sun4/io/efcode/fc_subr.c14
-rw-r--r--usr/src/uts/sun4/io/efcode/fcode.c65
2 files changed, 75 insertions, 4 deletions
diff --git a/usr/src/uts/sun4/io/efcode/fc_subr.c b/usr/src/uts/sun4/io/efcode/fc_subr.c
index 834e82db4c..a49ad53b4d 100644
--- a/usr/src/uts/sun4/io/efcode/fc_subr.c
+++ b/usr/src/uts/sun4/io/efcode/fc_subr.c
@@ -20,8 +20,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -245,6 +245,16 @@ fcode_timer(void *arg)
mutex_exit(&fc_request_lock);
cv_broadcast(&fc_request_cv);
return;
+ } else if (fp->error != FC_SUCCESS) {
+ /*
+ * An error was detected, but didn't close the driver.
+ * This will allow the process to error out, returning
+ * the interpreter error code instead of FC_TIMEOUT.
+ */
+ fp->busy = FC_R_DONE;
+ cv_broadcast(&fc_request_cv);
+ mutex_exit(&fc_request_lock);
+ return;
} else {
cmn_err(CE_WARN, "fcode_timer: Timeout waiting for "
"interpreter - Interpreter is executing request\n");
diff --git a/usr/src/uts/sun4/io/efcode/fcode.c b/usr/src/uts/sun4/io/efcode/fcode.c
index 0f0b4b54f1..f98ed8db01 100644
--- a/usr/src/uts/sun4/io/efcode/fcode.c
+++ b/usr/src/uts/sun4/io/efcode/fcode.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,6 +59,7 @@ static struct fc_state {
#define FC_STATE_READ_DONE 2 /* blocking read done */
#define FC_STATE_IN_PROGRESS 3 /* FC_GET_PARAMETERS done, active */
#define FC_STATE_VALIDATED 4 /* FC_VALIDATE done, active */
+#define FC_STATE_ERROR_SET 5 /* FC_SET_FCODE_ERROR done, active */
#define FC_STATE_ACTIVE(s) ((s) != 0)
#define FC_STATE_AVAILABLE(s) ((s) == FC_STATE_INACTIVE)
@@ -79,6 +80,7 @@ static int fc_get_my_args(dev_t, intptr_t, int, cred_t *, int *);
static int fc_run_priv(dev_t, intptr_t, int, cred_t *, int *);
static int fc_validate(dev_t, intptr_t, int, cred_t *, int *);
static int fc_get_fcode(dev_t, intptr_t, int, cred_t *, int *);
+static int fc_set_fcode_error(dev_t, intptr_t, int, cred_t *, int *);
static struct cb_ops fc_cb_ops = {
fc_open, /* open */
@@ -335,7 +337,13 @@ fc_close(dev_t dev, int flag, int otype, cred_t *cred_p)
"fc_close: Send invalidate cmd\n");
cp->svc_name = fc_ptr2cell(FC_SVC_INVALIDATE);
(void) fp->ap_ops(fp->ap_dip, fp->handle, cp);
- fp->error = FC_ERROR;
+ if ((st->state != FC_STATE_ERROR_SET) ||
+ (fp->error == FC_SUCCESS)) {
+ fp->error = FC_ERROR;
+ }
+ /*
+ * else - fp->error already set by userland interpreter
+ */
}
bzero(cp, sizeof (struct fc_client_interface));
@@ -464,6 +472,12 @@ fc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
*/
return (fc_get_fcode(dev, arg, mode, credp, rvalp));
+
+ case FC_SET_FCODE_ERROR:
+ /*
+ * Copy in interpreter error status
+ */
+ return (fc_set_fcode_error(dev, arg, mode, credp, rvalp));
}
/*
* Invalid ioctl command
@@ -859,3 +873,50 @@ fc_get_fcode(dev_t dev, intptr_t arg, int mode, cred_t *credp, int *rvalp)
return (0);
}
+
+/*
+ * fc_set_fcode_error: Copy in fcode error.
+ * The input 'arg' is a pointer to int which
+ * should have the appropriate error code set.
+ */
+
+/*ARGSUSED*/
+static int
+fc_set_fcode_error(dev_t dev, intptr_t arg, int mode, cred_t *credp, int *rvalp)
+{
+ struct fc_state *st;
+ struct fc_request *fp;
+ int m = (int)getminor(dev) - 1;
+ int status;
+
+ st = fc_states + m;
+ ASSERT(m < fc_max_opens && FC_STATE_ACTIVE(st->state));
+
+ ASSERT(st->req != NULL);
+ fp = st->req;
+
+ FC_DEBUG1(3, CE_CONT, "fc_ioctl: fc_set_fcode_error fp: %p\n", fp);
+
+ /*
+ * Get the error code from userland.
+ * We expect these to be negative values to denote
+ * interpreter errors.
+ */
+ if (copyin((void *)arg, &status, sizeof (int))) {
+ FC_DEBUG1(1, CE_CONT, "fc_ioctl: fc_set_fcode_error "
+ "fault copying in status from %p\n", arg);
+ return (EFAULT);
+ }
+
+ if (!FC_ERROR_VALID(status)) {
+ FC_DEBUG1(1, CE_CONT, "fc_ioctl: fc_set_fcode_error "
+ "invalid error code specified %i\n", status);
+ return (EINVAL);
+ }
+ fp->error = status;
+ mutex_enter(&fc_open_lock);
+ st->state = FC_STATE_ERROR_SET;
+ mutex_exit(&fc_open_lock);
+
+ return (0);
+}