diff options
Diffstat (limited to 'usr/src/uts/sun4/io/efcode')
-rw-r--r-- | usr/src/uts/sun4/io/efcode/fc_subr.c | 14 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/efcode/fcode.c | 65 |
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); +} |