4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
21 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
23 /* All Rights Reserved */
26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
32 * PS/2 type Mouse Module - Streams
35 #include <sys/param.h>
36 #include <sys/types.h>
38 #include <sys/signal.h>
39 #include <sys/errno.h>
41 #include <sys/termio.h>
42 #include <sys/stream.h>
43 #include <sys/stropts.h>
44 #include <sys/strtty.h>
45 #include <sys/strsun.h>
46 #include <sys/debug.h>
49 #include <sys/cmn_err.h>
50 #include <sys/sunddi.h>
52 #include <sys/promif.h>
55 #include <sys/i8042.h>
57 #include <sys/mouse.h>
59 #define DRIVER_NAME(dip) ddi_driver_name(dip)
61 #define MOUSE8042_INTERNAL_OPEN(minor) (((minor) & 0x1) == 1)
62 #define MOUSE8042_MINOR_TO_INSTANCE(minor) ((minor) / 2)
63 #define MOUSE8042_INTERNAL_MINOR(minor) ((minor) + 1)
65 #define MOUSE8042_RESET_TIMEOUT_USECS 500000 /* 500 ms */
67 extern int ddi_create_internal_pathname(dev_info_t
*, char *, int, minor_t
);
68 extern void consconfig_link(major_t major
, minor_t minor
);
69 extern int consconfig_unlink(major_t major
, minor_t minor
);
79 * We only support one instance. Yes, it's theoretically possible to
80 * plug in more than one, but it's not worth the implementation cost.
82 * The introduction of USB keyboards might make it worth reassessing
83 * this decision, as they might free up the keyboard port for a second
86 static dev_info_t
*mouse8042_dip
;
92 MSE_RESET_IDLE
, /* No reset in progress */
93 MSE_RESET_PRE
, /* Send reset, waiting for ACK */
94 MSE_RESET_ACK
, /* Got ACK, waiting for 0xAA */
95 MSE_RESET_AA
, /* Got 0xAA, waiting for 0x00 */
97 } mouse8042_reset_state_e
;
102 ddi_iblock_cookie_t ms_iblock_cookie
;
103 ddi_acc_handle_t ms_handle
;
109 kmutex_t reset_mutex
;
111 mouse8042_reset_state_e reset_state
;
112 timeout_id_t reset_tid
;
115 mblk_t
*reset_ack_mp
;
119 static uint_t
mouse8042_intr(caddr_t arg
);
120 static int mouse8042_open(queue_t
*q
, dev_t
*devp
, int flag
, int sflag
,
122 static int mouse8042_close(queue_t
*q
, int flag
, cred_t
*cred_p
);
123 static int mouse8042_wsrv(queue_t
*qp
);
124 static int mouse8042_wput(queue_t
*q
, mblk_t
*mp
);
126 static int mouse8042_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
127 void *arg
, void **result
);
128 static int mouse8042_attach(dev_info_t
*dev
, ddi_attach_cmd_t cmd
);
129 static int mouse8042_detach(dev_info_t
*dev
, ddi_detach_cmd_t cmd
);
133 * Streams module info.
135 #define MODULE_NAME "mouse8042"
137 static struct module_info mouse8042_minfo
= {
138 23, /* Module ID number */
140 0, INFPSZ
, /* minimum & maximum packet sizes */
141 256, 128 /* hi and low water marks */
144 static struct qinit mouse8042_rinit
= {
151 NULL
/* statistics */
154 static struct qinit mouse8042_winit
= {
155 mouse8042_wput
, /* put */
156 mouse8042_wsrv
, /* service */
161 NULL
/* statistics */
164 static struct streamtab mouse8042_strinfo
= {
172 * Local Function Declarations
175 static struct cb_ops mouse8042_cb_ops
= {
178 nodev
, /* strategy */
188 ddi_prop_op
, /* cb_prop_op */
189 &mouse8042_strinfo
, /* streamtab */
194 static struct dev_ops mouse8042_ops
= {
195 DEVO_REV
, /* devo_rev, */
197 mouse8042_getinfo
, /* getinfo */
198 nulldev
, /* identify */
200 mouse8042_attach
, /* attach */
201 mouse8042_detach
, /* detach */
203 &mouse8042_cb_ops
, /* driver operations */
204 (struct bus_ops
*)0, /* bus operations */
206 ddi_quiesce_not_needed
, /* quiesce */
210 * This is the loadable module wrapper.
212 #include <sys/modctl.h>
214 extern struct mod_ops mod_driverops
;
217 * Module linkage information for the kernel.
220 static struct modldrv modldrv
= {
221 &mod_driverops
, /* Type of module. This one is a driver */
223 &mouse8042_ops
, /* driver ops */
226 static struct modlinkage modlinkage
= {
233 * This is the driver initialization routine.
240 rv
= mod_install(&modlinkage
);
248 return (mod_remove(&modlinkage
));
253 _info(struct modinfo
*modinfop
)
255 return (mod_info(&modlinkage
, modinfop
));
259 mouse8042_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
261 struct mouse_state
*state
;
263 int instance
= ddi_get_instance(dip
);
264 static ddi_device_acc_attr_t attr
= {
272 if (cmd
== DDI_RESUME
) {
273 state
= (struct mouse_state
*)ddi_get_driver_private(dip
);
275 /* Ready to handle inbound data from mouse8042_intr */
279 * Send a 0xaa 0x00 upstream.
280 * This causes the vuid module to reset the mouse.
282 if (state
->ms_rqp
!= NULL
) {
283 if (mp
= allocb(1, BPRI_MED
)) {
284 *mp
->b_wptr
++ = 0xaa;
285 putnext(state
->ms_rqp
, mp
);
287 if (mp
= allocb(1, BPRI_MED
)) {
289 putnext(state
->ms_rqp
, mp
);
292 return (DDI_SUCCESS
);
295 if (cmd
!= DDI_ATTACH
)
296 return (DDI_FAILURE
);
298 if (mouse8042_dip
!= NULL
)
299 return (DDI_FAILURE
);
301 /* allocate and initialize state structure */
302 state
= kmem_zalloc(sizeof (struct mouse_state
), KM_SLEEP
);
303 state
->ms_opened
= B_FALSE
;
304 state
->reset_state
= MSE_RESET_IDLE
;
305 state
->reset_tid
= 0;
307 ddi_set_driver_private(dip
, state
);
310 * In order to support virtual keyboard/mouse, we should distinguish
311 * between internal virtual open and external physical open.
313 * When the physical devices are opened by application, they will
314 * be unlinked from the virtual device and their data stream will
315 * not be sent to the virtual device. When the opened physical
316 * devices are closed, they will be relinked to the virtual devices.
318 * All these automatic switch between virtual and physical are
321 * So we change minor node numbering scheme to be:
322 * external node minor num == instance * 2
323 * internal node minor num == instance * 2 + 1
325 rc
= ddi_create_minor_node(dip
, "mouse", S_IFCHR
, instance
* 2,
327 if (rc
!= DDI_SUCCESS
) {
331 if (ddi_create_internal_pathname(dip
, "internal_mouse", S_IFCHR
,
332 instance
* 2 + 1) != DDI_SUCCESS
) {
336 rc
= ddi_regs_map_setup(dip
, 0, (caddr_t
*)&state
->ms_addr
,
337 (offset_t
)0, (offset_t
)0, &attr
, &state
->ms_handle
);
338 if (rc
!= DDI_SUCCESS
) {
342 rc
= ddi_get_iblock_cookie(dip
, 0, &state
->ms_iblock_cookie
);
343 if (rc
!= DDI_SUCCESS
) {
347 mutex_init(&state
->ms_mutex
, NULL
, MUTEX_DRIVER
,
348 state
->ms_iblock_cookie
);
349 mutex_init(&state
->reset_mutex
, NULL
, MUTEX_DRIVER
,
350 state
->ms_iblock_cookie
);
351 cv_init(&state
->reset_cv
, NULL
, CV_DRIVER
, NULL
);
353 rc
= ddi_add_intr(dip
, 0,
354 (ddi_iblock_cookie_t
*)NULL
, (ddi_idevice_cookie_t
*)NULL
,
355 mouse8042_intr
, (caddr_t
)state
);
356 if (rc
!= DDI_SUCCESS
) {
362 /* Ready to handle inbound data from mouse8042_intr */
365 /* Now that we're attached, announce our presence to the world. */
367 return (DDI_SUCCESS
);
370 ddi_regs_map_free(&state
->ms_handle
);
373 ddi_remove_minor_node(dip
, NULL
);
376 kmem_free(state
, sizeof (struct mouse_state
));
382 mouse8042_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
384 struct mouse_state
*state
;
386 state
= ddi_get_driver_private(dip
);
390 /* Ignore all data from mouse8042_intr until we fully resume */
392 return (DDI_SUCCESS
);
395 ddi_remove_intr(dip
, 0, state
->ms_iblock_cookie
);
396 mouse8042_dip
= NULL
;
397 cv_destroy(&state
->reset_cv
);
398 mutex_destroy(&state
->reset_mutex
);
399 mutex_destroy(&state
->ms_mutex
);
400 ddi_prop_remove_all(dip
);
401 ddi_regs_map_free(&state
->ms_handle
);
402 ddi_remove_minor_node(dip
, NULL
);
403 kmem_free(state
, sizeof (struct mouse_state
));
404 return (DDI_SUCCESS
);
407 return (DDI_FAILURE
);
416 ddi_info_cmd_t infocmd
,
420 dev_t dev
= (dev_t
)arg
;
421 minor_t minor
= getminor(dev
);
422 int instance
= MOUSE8042_MINOR_TO_INSTANCE(minor
);
425 case DDI_INFO_DEVT2DEVINFO
:
426 if (mouse8042_dip
== NULL
)
427 return (DDI_FAILURE
);
429 *result
= (void *)mouse8042_dip
;
431 case DDI_INFO_DEVT2INSTANCE
:
432 *result
= (void *)(uintptr_t)instance
;
435 return (DDI_FAILURE
);
437 return (DDI_SUCCESS
);
449 struct mouse_state
*state
;
450 minor_t minor
= getminor(*devp
);
453 if (mouse8042_dip
== NULL
)
456 state
= ddi_get_driver_private(mouse8042_dip
);
458 mutex_enter(&state
->ms_mutex
);
460 if (state
->ms_opened
) {
462 * Exit if the same minor node is already open
464 if (state
->ms_minor
== minor
) {
465 mutex_exit(&state
->ms_mutex
);
470 * Check whether it is switch between physical and virtual
472 * Opening from virtual while the device is being physically
473 * opened by an application should not happen. So we ASSERT
474 * this in DEBUG version, and return error in the non-DEBUG
477 ASSERT(!MOUSE8042_INTERNAL_OPEN(minor
));
479 if (MOUSE8042_INTERNAL_OPEN(minor
)) {
480 mutex_exit(&state
->ms_mutex
);
485 * Opening the physical one while it is being underneath
488 * consconfig_unlink is called to unlink this device from
489 * the virtual one, thus the old stream serving for this
490 * device under the virtual one is closed, and then the
491 * lower driver's close routine (here is mouse8042_close)
492 * is also called to accomplish the whole stream close.
493 * Here we have to drop the lock because mouse8042_close
494 * also needs the lock.
496 * For mouse, the old stream is:
497 * consms->["pushmod"->]"mouse_vp driver"
499 * After the consconfig_unlink returns, the old stream is closed
500 * and we grab the lock again to reopen this device as normal.
502 mutex_exit(&state
->ms_mutex
);
505 * If unlink fails, fail the physical open.
507 if ((rval
= consconfig_unlink(ddi_driver_major(mouse8042_dip
),
508 MOUSE8042_INTERNAL_MINOR(minor
))) != 0) {
512 mutex_enter(&state
->ms_mutex
);
516 q
->q_ptr
= (caddr_t
)state
;
517 WR(q
)->q_ptr
= (caddr_t
)state
;
519 state
->ms_wqp
= WR(q
);
523 state
->ms_minor
= minor
;
524 state
->ms_opened
= B_TRUE
;
526 mutex_exit(&state
->ms_mutex
);
534 mouse8042_close(queue_t
*q
, int flag
, cred_t
*cred_p
)
536 struct mouse_state
*state
;
539 state
= (struct mouse_state
*)q
->q_ptr
;
542 * Disable queue processing now, so that another reset cannot get in
543 * after we wait for the current reset (if any) to complete.
547 mutex_enter(&state
->reset_mutex
);
548 while (state
->reset_state
!= MSE_RESET_IDLE
) {
550 * Waiting for the previous reset to finish is
551 * non-interruptible. Some upper-level clients
552 * cannot deal with EINTR and will not close the
553 * STREAM properly, resulting in failure to reopen it
554 * within the same process.
556 cv_wait(&state
->reset_cv
, &state
->reset_mutex
);
559 if (state
->reset_tid
!= 0) {
560 (void) quntimeout(q
, state
->reset_tid
);
561 state
->reset_tid
= 0;
564 if (state
->reply_mp
!= NULL
) {
565 freemsg(state
->reply_mp
);
566 state
->reply_mp
= NULL
;
569 if (state
->reset_ack_mp
!= NULL
) {
570 freemsg(state
->reset_ack_mp
);
571 state
->reset_ack_mp
= NULL
;
574 mutex_exit(&state
->reset_mutex
);
576 mutex_enter(&state
->ms_mutex
);
578 if (state
->bc_id
!= 0) {
579 (void) qunbufcall(q
, state
->bc_id
);
585 state
->ms_rqp
= NULL
;
586 state
->ms_wqp
= NULL
;
588 state
->ms_opened
= B_FALSE
;
590 minor
= state
->ms_minor
;
592 mutex_exit(&state
->ms_mutex
);
594 if (!MOUSE8042_INTERNAL_OPEN(minor
)) {
596 * Closing physical PS/2 mouse
598 * Link it back to virtual mouse, and
599 * mouse8042_open will be called as a result
600 * of the consconfig_link call. Do NOT try
601 * this if the mouse is about to be detached!
603 * If linking back fails, this specific mouse
604 * will not be available underneath the virtual
605 * mouse, and can only be accessed via physical
608 consconfig_link(ddi_driver_major(mouse8042_dip
),
609 MOUSE8042_INTERNAL_MINOR(minor
));
623 mp
->b_datap
->db_type
= M_IOCNAK
;
624 iocp
->ioc_rval
= rval
;
625 iocp
->ioc_error
= error
;
630 mouse8042_reset_timeout(void *argp
)
632 struct mouse_state
*state
= (struct mouse_state
*)argp
;
635 mutex_enter(&state
->reset_mutex
);
638 * If the interrupt handler hasn't completed the reset handling
639 * (reset_state would be IDLE or FAILED in that case), then
640 * drop the 8042 lock, and send a faked retry reply upstream,
641 * then enable the queue for further message processing.
643 if (state
->reset_state
!= MSE_RESET_IDLE
&&
644 state
->reset_state
!= MSE_RESET_FAILED
) {
646 state
->reset_tid
= 0;
647 state
->reset_state
= MSE_RESET_IDLE
;
648 cv_signal(&state
->reset_cv
);
650 (void) ddi_get8(state
->ms_handle
, state
->ms_addr
+
653 mp
= state
->reply_mp
;
654 *mp
->b_wptr
++ = MSERESEND
;
655 state
->reply_mp
= NULL
;
657 if (state
->ms_rqp
!= NULL
)
658 putnext(state
->ms_rqp
, mp
);
662 ASSERT(state
->ms_wqp
!= NULL
);
664 enableok(state
->ms_wqp
);
665 qenable(state
->ms_wqp
);
668 mutex_exit(&state
->reset_mutex
);
672 * Returns 1 if the caller should put the message (bp) back on the queue
675 mouse8042_initiate_reset(queue_t
*q
, mblk_t
*mp
, struct mouse_state
*state
)
677 mutex_enter(&state
->reset_mutex
);
679 * If we're in the middle of a reset, put the message back on the queue
680 * for processing later.
682 if (state
->reset_state
!= MSE_RESET_IDLE
) {
684 * We noenable the queue again here in case it was backenabled
685 * by an upper-level module.
689 mutex_exit(&state
->reset_mutex
);
694 * Drop the reset state lock before allocating the response message and
695 * grabbing the 8042 exclusive-access lock (since those operations
696 * may take an extended period of time to complete).
698 mutex_exit(&state
->reset_mutex
);
700 if (state
->reply_mp
== NULL
)
701 state
->reply_mp
= allocb(2, BPRI_MED
);
702 if (state
->reset_ack_mp
== NULL
)
703 state
->reset_ack_mp
= allocb(1, BPRI_MED
);
705 if (state
->reply_mp
== NULL
|| state
->reset_ack_mp
== NULL
) {
707 * Allocation failed -- set up a bufcall to enable the queue
708 * whenever there is enough memory to allocate the response
711 state
->bc_id
= qbufcall(q
, (state
->reply_mp
== NULL
) ? 2 : 1,
712 BPRI_MED
, (void (*)(void *))qenable
, q
);
714 if (state
->bc_id
== 0) {
716 * If the qbufcall failed, we cannot proceed, so use the
717 * message we were sent to respond with an error.
719 *mp
->b_rptr
= MSEERROR
;
720 mp
->b_wptr
= mp
->b_rptr
+ 1;
727 /* Bufcall completed successfully (or wasn't needed) */
732 * Gain exclusive access to the 8042 for the duration of the reset.
733 * The unlock will occur when the reset has either completed or timed
736 (void) ddi_get8(state
->ms_handle
,
737 state
->ms_addr
+ I8042_LOCK
);
739 mutex_enter(&state
->reset_mutex
);
741 state
->reset_state
= MSE_RESET_PRE
;
744 state
->reset_tid
= qtimeout(q
,
745 mouse8042_reset_timeout
,
748 MOUSE8042_RESET_TIMEOUT_USECS
));
750 ddi_put8(state
->ms_handle
,
752 I8042_INT_OUTPUT_DATA
, MSERESET
);
756 mutex_exit(&state
->reset_mutex
);
761 * Returns 1 if the caller should stop processing messages
764 mouse8042_process_data_msg(queue_t
*q
, mblk_t
*mp
, struct mouse_state
*state
)
771 while (bp
->b_rptr
< bp
->b_wptr
) {
773 * Detect an attempt to reset the mouse. Lock out any
774 * further mouse writes until the reset has completed.
776 if (*bp
->b_rptr
== MSERESET
) {
779 * If we couldn't allocate memory and we
780 * we couldn't register a bufcall,
781 * mouse8042_initiate_reset returns 0 and
782 * has already used the message to send an
783 * error reply back upstream, so there is no
784 * need to deallocate or put this message back
787 if (mouse8042_initiate_reset(q
, bp
, state
) == 0)
791 * If there's no data remaining in this block,
792 * free this block and put the following blocks
793 * of this message back on the queue. If putting
794 * the rest of the message back on the queue
795 * fails, free the the message.
797 if (MBLKL(bp
) == 0) {
810 ddi_put8(state
->ms_handle
,
811 state
->ms_addr
+ I8042_INT_OUTPUT_DATA
,
816 } while ((bp
= next
) != NULL
);
822 mouse8042_process_msg(queue_t
*q
, mblk_t
*mp
, struct mouse_state
*state
)
824 struct iocblk
*iocbp
;
827 iocbp
= (struct iocblk
*)mp
->b_rptr
;
829 switch (mp
->b_datap
->db_type
) {
831 if (*mp
->b_rptr
& FLUSHW
) {
832 flushq(q
, FLUSHDATA
);
833 *mp
->b_rptr
&= ~FLUSHW
;
835 if (*mp
->b_rptr
& FLUSHR
) {
841 mouse8042_iocnack(q
, mp
, iocbp
, EINVAL
, 0);
844 mouse8042_iocnack(q
, mp
, iocbp
, EINVAL
, 0);
847 rv
= mouse8042_process_data_msg(q
, mp
, state
);
858 * This is the main mouse input routine. Commands and parameters
859 * from upstream are sent to the mouse device immediately, unless
860 * the mouse is in the process of being reset, in which case
861 * commands are queued and executed later in the service procedure.
864 mouse8042_wput(queue_t
*q
, mblk_t
*mp
)
866 struct mouse_state
*state
;
867 state
= (struct mouse_state
*)q
->q_ptr
;
870 * Process all messages immediately, unless a reset is in
871 * progress. If a reset is in progress, deflect processing to
872 * the service procedure.
874 if (state
->reset_state
!= MSE_RESET_IDLE
)
875 return (putq(q
, mp
));
878 * If there are still messages outstanding in the queue that
879 * the service procedure hasn't processed yet, put this
880 * message in the queue also, to ensure proper message
884 return (putq(q
, mp
));
886 (void) mouse8042_process_msg(q
, mp
, state
);
892 mouse8042_wsrv(queue_t
*qp
)
895 struct mouse_state
*state
;
896 state
= (struct mouse_state
*)qp
->q_ptr
;
898 while ((mp
= getq(qp
)) != NULL
) {
899 if (mouse8042_process_msg(qp
, mp
, state
) != 0)
907 * Returns the next reset state, given the current state and the byte
908 * received from the mouse. Error and Resend codes are handled by the
911 static mouse8042_reset_state_e
912 mouse8042_reset_fsm(mouse8042_reset_state_e reset_state
, uint8_t mdata
)
914 switch (reset_state
) {
915 case MSE_RESET_PRE
: /* RESET sent, now we expect an ACK */
916 if (mdata
== MSE_ACK
) /* Got the ACK */
917 return (MSE_RESET_ACK
);
920 case MSE_RESET_ACK
: /* ACK received; now we expect 0xAA */
921 if (mdata
== MSE_AA
) /* Got the 0xAA */
922 return (MSE_RESET_AA
);
925 case MSE_RESET_AA
: /* 0xAA received; now we expect 0x00 */
927 return (MSE_RESET_IDLE
);
931 return (reset_state
);
935 mouse8042_intr(caddr_t arg
)
939 struct mouse_state
*state
= (struct mouse_state
*)arg
;
942 mutex_enter(&state
->ms_mutex
);
944 rc
= DDI_INTR_UNCLAIMED
;
948 if (ddi_get8(state
->ms_handle
,
949 state
->ms_addr
+ I8042_INT_INPUT_AVAIL
) == 0) {
953 mdata
= ddi_get8(state
->ms_handle
,
954 state
->ms_addr
+ I8042_INT_INPUT_DATA
);
956 rc
= DDI_INTR_CLAIMED
;
959 * If we're not ready for this data, discard it.
964 mutex_enter(&state
->reset_mutex
);
965 if (state
->reset_state
!= MSE_RESET_IDLE
) {
967 if (mdata
== MSEERROR
|| mdata
== MSERESET
) {
968 state
->reset_state
= MSE_RESET_FAILED
;
971 mouse8042_reset_fsm(state
->reset_state
,
975 if (state
->reset_state
== MSE_RESET_ACK
) {
978 * We received an ACK from the mouse, so
979 * send it upstream immediately so that
980 * consumers depending on the immediate
981 * ACK don't time out.
983 if (state
->reset_ack_mp
!= NULL
) {
985 mp
= state
->reset_ack_mp
;
987 state
->reset_ack_mp
= NULL
;
989 if (state
->ms_rqp
!= NULL
) {
990 *mp
->b_wptr
++ = MSE_ACK
;
991 putnext(state
->ms_rqp
, mp
);
996 if (state
->ms_wqp
!= NULL
) {
997 enableok(state
->ms_wqp
);
998 qenable(state
->ms_wqp
);
1001 } else if (state
->reset_state
== MSE_RESET_IDLE
||
1002 state
->reset_state
== MSE_RESET_FAILED
) {
1005 * If we transitioned back to the idle reset state (or
1006 * the reset failed), disable the timeout, release the
1007 * 8042 exclusive-access lock, then send the response
1008 * the the upper-level modules. Finally, enable the
1009 * queue and schedule queue service procedures so that
1010 * upper-level modules can process the response.
1011 * Otherwise, if we're still in the middle of the
1012 * reset sequence, do not send the data up (since the
1013 * response is sent at the end of the sequence, or
1014 * on timeout/error).
1017 mutex_exit(&state
->reset_mutex
);
1018 (void) quntimeout(state
->ms_wqp
,
1020 mutex_enter(&state
->reset_mutex
);
1022 (void) ddi_get8(state
->ms_handle
,
1023 state
->ms_addr
+ I8042_UNLOCK
);
1025 state
->reset_tid
= 0;
1026 if (state
->reply_mp
!= NULL
) {
1027 mp
= state
->reply_mp
;
1028 if (state
->reset_state
==
1030 *mp
->b_wptr
++ = mdata
;
1032 *mp
->b_wptr
++ = MSE_AA
;
1033 *mp
->b_wptr
++ = MSE_00
;
1035 state
->reply_mp
= NULL
;
1040 state
->reset_state
= MSE_RESET_IDLE
;
1041 cv_signal(&state
->reset_cv
);
1044 if (state
->ms_rqp
!= NULL
)
1045 putnext(state
->ms_rqp
, mp
);
1050 if (state
->ms_wqp
!= NULL
) {
1051 enableok(state
->ms_wqp
);
1052 qenable(state
->ms_wqp
);
1056 mutex_exit(&state
->reset_mutex
);
1057 mutex_exit(&state
->ms_mutex
);
1060 mutex_exit(&state
->reset_mutex
);
1062 if (state
->ms_rqp
!= NULL
&& (mp
= allocb(1, BPRI_MED
))) {
1063 *mp
->b_wptr
++ = mdata
;
1064 putnext(state
->ms_rqp
, mp
);
1067 mutex_exit(&state
->ms_mutex
);