psm.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,239 行 · 第 1/5 页

C
2,239
字号
    if (verbose >= 2)        log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res);    return (res == PSM_ACK);}#endif /* PSM_RESETAFTERSUSPEND */static intget_mouse_buttons(KBDC kbdc){    int c = 2;		/* assume two buttons by default */    int status[3];    /*     * NOTE: a special sequence to obtain Logitech Mouse specific     * information: set resolution to 25 ppi, set scaling to 1:1, set     * scaling to 1:1, set scaling to 1:1. Then the second byte of the     * mouse status bytes is the number of available buttons.     * Some manufactures also support this sequence.     */    if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)        return c;    if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1)        && set_mouse_scaling(kbdc, 1) 	&& (get_mouse_status(kbdc, status, 0, 3) >= 3)) {        if (status[1] != 0)            return status[1];    }    return c;}/* misc subroutines *//* * Someday, I will get the complete list of valid pointing devices and * their IDs... XXX */static intis_a_mouse(int id){#if 0    static int valid_ids[] = {        PSM_MOUSE_ID,		/* mouse */        PSM_BALLPOINT_ID,	/* ballpoint device */        PSM_INTELLI_ID,		/* Intellimouse */        -1			/* end of table */    };    int i;    for (i = 0; valid_ids[i] >= 0; ++i)        if (valid_ids[i] == id)            return TRUE;    return FALSE;#else    return TRUE;#endif}static char *model_name(int model){    static struct {	int model_code;	char *model_name;    } models[] = {        { MOUSE_MODEL_NETSCROLL,	"NetScroll Mouse" },        { MOUSE_MODEL_NET,		"NetMouse" },        { MOUSE_MODEL_GLIDEPOINT,	"GlidePoint" },        { MOUSE_MODEL_THINK,		"ThinkingMouse" },        { MOUSE_MODEL_INTELLI,		"IntelliMouse" },        { MOUSE_MODEL_MOUSEMANPLUS,	"MouseMan+" },        { MOUSE_MODEL_GENERIC,		"Generic PS/2 mouse" },        { MOUSE_MODEL_UNKNOWN,		NULL },    };    int i;    for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) {	if (models[i].model_code == model)	    return models[i].model_name;    }    return "Unknown";}static voidrecover_from_error(KBDC kbdc){    /* discard anything left in the output buffer */    empty_both_buffers(kbdc, 10);#if 0    /*     * NOTE: KBDC_RESET_KBD may not restore the communication between the     * keyboard and the controller.     */    reset_kbd(kbdc);#else    /*     * NOTE: somehow diagnostic and keyboard port test commands bring the     * keyboard back.     */    if (!test_controller(kbdc))         log(LOG_ERR, "psm: keyboard controller failed.\n");    /* if there isn't a keyboard in the system, the following error is OK */    if (test_kbd_port(kbdc) != 0) {	if (verbose)	    log(LOG_ERR, "psm: keyboard port failed.\n");    }#endif}static intrestore_controller(KBDC kbdc, int command_byte){    empty_both_buffers(kbdc, 10);    if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {	log(LOG_ERR, "psm: failed to restore the keyboard controller "		     "command byte.\n");	return FALSE;    } else {	return TRUE;    }}#ifdef PSM_RESETAFTERSUSPEND/*  * Re-initialize the aux port and device. The aux port must be enabled * and its interrupt must be disabled before calling this routine.  * The aux device will be disabled before returning. * The keyboard controller must be locked via `kbdc_lock()' before * calling this routine. */static intreinitialize(int unit, mousemode_t *mode){    struct psm_softc *sc = psm_softc[unit];    KBDC kbdc = psm_softc[unit]->kbdc;    int stat[3];    int i;    switch((i = test_aux_port(kbdc))) {    case 1:	/* ignore this error */    case PSM_ACK:	if (verbose)	    log(LOG_DEBUG, "psm%d: strange result for test aux port (%d).\n",	        unit, i);	/* fall though */    case 0:	/* no error */    	break;    case -1: 	/* time out */    default: 	/* error */    	recover_from_error(kbdc);	if (sc->config & PSM_CONFIG_IGNPORTERROR)	    break;    	log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n",    	    unit, i);    	return FALSE;    }    if (sc->config & PSM_CONFIG_NORESET) {	/* 	 * Don't try to reset the pointing device.  It may possibly be	 * left in the unknown state, though...	 */    } else {	/* 	 * NOTE: some controllers appears to hang the `keyboard' when	 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 	 */	if (!reset_aux_dev(kbdc)) {            recover_from_error(kbdc);            log(LOG_ERR, "psm%d: failed to reset the aux device.\n", unit);            return FALSE;	}    }    /*      * both the aux port and the aux device is functioning, see     * if the device can be enabled.      */    if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) {        log(LOG_ERR, "psm%d: failed to enable the aux device.\n", unit);        return FALSE;    }    empty_both_buffers(kbdc, 10);	/* remove stray data if any */    if (sc->config & PSM_CONFIG_NOIDPROBE) {	i = GENERIC_MOUSE_ENTRY;    } else {	/* FIXME: hardware ID, mouse buttons? */	/* other parameters */	for (i = 0; vendortype[i].probefunc != NULL; ++i) {	    if ((*vendortype[i].probefunc)(sc)) {		if (verbose >= 2)		    log(LOG_ERR, "psm%d: found %s\n", 			unit, model_name(vendortype[i].model));		break;	    }	}    }    sc->hw.model = vendortype[i].model;    sc->mode.packetsize = vendortype[i].packetsize;    /* set mouse parameters */    if (mode != (mousemode_t *)NULL) {	if (mode->rate > 0)            mode->rate = set_mouse_sampling_rate(kbdc, mode->rate);	if (mode->resolution >= 0)            mode->resolution = set_mouse_resolution(kbdc, mode->resolution);        set_mouse_scaling(kbdc, 1);        set_mouse_mode(kbdc);	    }    /* request a data packet and extract sync. bits */    if (get_mouse_status(kbdc, stat, 1, 3) < 3) {        log(LOG_DEBUG, "psm%d: failed to get data (reinitialize).\n", unit);        sc->mode.syncmask[0] = 0;    } else {        sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0];	/* syncbits */	/* the NetScroll Mouse will send three more bytes... Ignore them */	empty_aux_buffer(kbdc, 5);    }    /* just check the status of the mouse */    if (get_mouse_status(kbdc, stat, 0, 3) < 3)        log(LOG_DEBUG, "psm%d: failed to get status (reinitialize).\n", unit);    return TRUE;}#endif /* PSM_RESETAFTERSUSPEND */static intdoopen(int unit, int command_byte){    struct psm_softc *sc = psm_softc[unit];    int stat[3];    /* enable the mouse device */    if (!enable_aux_dev(sc->kbdc)) {	/* MOUSE ERROR: failed to enable the mouse because:	 * 1) the mouse is faulty,	 * 2) the mouse has been removed(!?)	 * In the latter case, the keyboard may have hung, and need 	 * recovery procedure...	 */	recover_from_error(sc->kbdc);#if 0	/* FIXME: we could reset the mouse here and try to enable	 * it again. But it will take long time and it's not a good	 * idea to disable the keyboard that long...	 */	if (!reinitialize(unit, &sc->mode) || !enable_aux_dev(sc->kbdc)) {	    recover_from_error(sc->kbdc);#else        {#endif            restore_controller(sc->kbdc, command_byte);	    /* mark this device is no longer available */	    sc->state &= ~PSM_VALID;		    log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n",		unit);	    return (EIO);	}    }    if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)         log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", unit);    /* enable the aux port and interrupt */    if (!set_controller_command_byte(sc->kbdc, 	    kbdc_get_device_mask(sc->kbdc),	    (command_byte & KBD_KBD_CONTROL_BITS)		| KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {	/* CONTROLLER ERROR */	disable_aux_dev(sc->kbdc);        restore_controller(sc->kbdc, command_byte);	log(LOG_ERR, "psm%d: failed to enable the aux interrupt (doopen).\n",	    unit);	return (EIO);    }    return (0);}/* psm driver entry points */#define endprobe(v)	{   if (bootverbose) 				\				--verbose;   				\                            kbdc_set_device_mask(sc->kbdc, mask);	\			    kbdc_lock(sc->kbdc, FALSE);			\ 	                    free(sc, M_DEVBUF);                         \			    return (v);	     				\			}static intpsmprobe(struct isa_device *dvp){    int unit = dvp->id_unit;    struct psm_softc *sc;    int stat[3];    int command_byte;    int mask;    int i;    /* validate unit number */    if (unit >= NPSM)        return (0);    psm_softc[unit] = NULL;    sc =  malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);    if (sc == NULL)        return (0);    bzero(sc, sizeof *sc);#if 0    kbdc_debug(TRUE);#endif    sc->addr = dvp->id_iobase;    sc->kbdc = kbdc_open(sc->addr);    sc->config = dvp->id_flags & PSM_CONFIG_FLAGS;    sc->flags = 0;    if (bootverbose)        ++verbose;    if (!kbdc_lock(sc->kbdc, TRUE)) {        printf("psm%d: unable to lock the controller.\n", unit);        if (bootverbose)            --verbose;        free(sc, M_DEVBUF);	return (0);    }    /*     * NOTE: two bits in the command byte controls the operation of the     * aux port (mouse port): the aux port disable bit (bit 5) and the aux     * port interrupt (IRQ 12) enable bit (bit 2).     */    /* discard anything left after the keyboard initialization */    empty_both_buffers(sc->kbdc, 10);    /* save the current command byte; it will be used later */    mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;    command_byte = get_controller_command_byte(sc->kbdc);    if (verbose)         printf("psm%d: current command byte:%04x\n", unit, command_byte);    if (command_byte == -1) {        /* CONTROLLER ERROR */        printf("psm%d: unable to get the current command byte value.\n",            unit);        endprobe(0);    }    /*     * disable the keyboard port while probing the aux port, which must be     * enabled during this routine     */    if (!set_controller_command_byte(sc->kbdc,	    KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,  	    KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT                | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {        /* 	 * this is CONTROLLER ERROR; I don't know how to recover          * from this error... 	 */        restore_controller(sc->kbdc, command_byte);        printf("psm%d: unable to set the command byte.\n", unit);        endprobe(0);    }    write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);    /*     * NOTE: `test_aux_port()' is designed to return with zero if the aux     * port exists and is functioning. However, some controllers appears     * to respond with zero even when the aux port doesn't exist. (It may     * be that this is only the case when the controller DOES have the aux     * port but the port is not wired on the motherboard.) The keyboard     * controllers without the port, such as the original AT, are     * supporsed to return with an error code or simply time out. In any     * case, we have to continue probing the port even when the controller     * passes this test.     *     * XXX: some controllers erroneously return the error code 1 when     * it has the perfectly functional aux port. We have to ignore this     * error code. Even if the controller HAS error with the aux port,     * it will be detected later...     * XXX: another incompatible controller returns PSM_ACK (0xfa)...     */    switch ((i = test_aux_port(sc->kbdc))) {    case 1:	   /* ignore this error */    case PSM_ACK:        if (verbose)	    printf("psm%d: strange result for test aux port (%d).\n",	        unit, i);	/* fall though */    case 0:        /* no error */        break;    case -1:        /* time out */    default:        /* error */        recover_from_error(sc->kbdc);	if (sc->config & PSM_CONFIG_IGNPORTERROR)	    break;        restore_controller(sc->kbdc, command_byte);        if (verbose)            printf("psm%d: the aux port is not functioning (%d).\n",                unit, i);        endprobe(0);    }    if (sc->config & PSM_CONFIG_NORESET) {	/* 	 * Don't try to reset the pointing device.  It may possibly be	 * left in the unknown state, though...	 */    } else {	/*	 * NOTE: some controllers appears to hang the `keyboard' when the aux	 * port doesn't exist and `PSMC_RESET_DEV' is issued.	 */	if (!reset_aux_dev(sc->kbdc)) {            recover_from_error(sc->kbdc);            restore_controller(sc->kbdc, command_byte);            if (verbose)        	printf("psm%d: failed to reset the aux device.\n", unit);            endprobe(0);	}    }    /*     * both the aux port and the aux device is functioning, see if the     * device can be enabled. NOTE: when enabled, the device will start     * sending data; we shall immediately disable the device once we know     * the device can be enabled.     */    if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {        /* MOUSE ERROR */	recover_from_error(sc->kbdc);	restore_controller(sc->kbdc, command_byte);	if (verbose)	    printf("psm%d: failed to enable the aux device.\n", unit);	endprobe(0);    }    /* save the default values after reset */    if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?